summaryrefslogtreecommitdiff
path: root/tex/context/base
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base')
-rw-r--r--tex/context/base/mkii/cont-new.mkii2
-rw-r--r--tex/context/base/mkii/context.mkii2
-rw-r--r--tex/context/base/mkii/core-sys.mkii12
-rw-r--r--tex/context/base/mkii/enco-agr.mkii3
-rw-r--r--tex/context/base/mkii/enco-def.mkii1
-rw-r--r--tex/context/base/mkii/enco-uc.mkii2
-rw-r--r--tex/context/base/mkii/mult-cs.mkii10
-rw-r--r--tex/context/base/mkii/mult-de.mkii8
-rw-r--r--tex/context/base/mkii/mult-en.mkii7
-rw-r--r--tex/context/base/mkii/mult-fr.mkii7
-rw-r--r--tex/context/base/mkii/mult-it.mkii8
-rw-r--r--tex/context/base/mkii/mult-nl.mkii12
-rw-r--r--tex/context/base/mkii/mult-pe.mkii7
-rw-r--r--tex/context/base/mkii/mult-ro.mkii8
-rw-r--r--tex/context/base/mkii/strc-reg.mkii4
-rw-r--r--tex/context/base/mkii/unic-003.mkii4
-rw-r--r--tex/context/base/mkii/xetx-chr.mkii1
-rw-r--r--tex/context/base/mkiv/anch-bck.mkvi24
-rw-r--r--tex/context/base/mkiv/anch-pgr.lua140
-rw-r--r--tex/context/base/mkiv/anch-pgr.mkiv14
-rw-r--r--tex/context/base/mkiv/anch-pos.lua166
-rw-r--r--tex/context/base/mkiv/anch-pos.mkiv18
-rw-r--r--tex/context/base/mkiv/anch-snc.lua271
-rw-r--r--tex/context/base/mkiv/anch-snc.mkiv272
-rw-r--r--tex/context/base/mkiv/anch-tab.mkiv17
-rw-r--r--tex/context/base/mkiv/attr-col.lua48
-rw-r--r--tex/context/base/mkiv/attr-ini.lua5
-rw-r--r--tex/context/base/mkiv/attr-ini.mkiv36
-rw-r--r--tex/context/base/mkiv/back-exp.lua936
-rw-r--r--tex/context/base/mkiv/back-exp.mkiv28
-rw-r--r--tex/context/base/mkiv/back-ini.lua221
-rw-r--r--tex/context/base/mkiv/back-ini.mkiv116
-rw-r--r--tex/context/base/mkiv/back-pdf.lua301
-rw-r--r--tex/context/base/mkiv/back-pdf.mkiv188
-rw-r--r--tex/context/base/mkiv/back-pdp.lua453
-rw-r--r--tex/context/base/mkiv/back-res.lua44
-rw-r--r--tex/context/base/mkiv/back-swf.mkiv101
-rw-r--r--tex/context/base/mkiv/bibl-bib.mkiv6
-rw-r--r--tex/context/base/mkiv/bibl-tra.mkiv2
-rw-r--r--tex/context/base/mkiv/buff-imp-default.mkiv10
-rw-r--r--tex/context/base/mkiv/buff-ini.lua25
-rw-r--r--tex/context/base/mkiv/buff-ini.mkiv46
-rw-r--r--tex/context/base/mkiv/buff-ver.lua23
-rw-r--r--tex/context/base/mkiv/buff-ver.mkiv19
-rw-r--r--tex/context/base/mkiv/catc-ini.mkiv161
-rw-r--r--tex/context/base/mkiv/char-act.mkiv47
-rw-r--r--tex/context/base/mkiv/char-def.lua5239
-rw-r--r--tex/context/base/mkiv/char-emj.lua2566
-rw-r--r--tex/context/base/mkiv/char-ini.lua60
-rw-r--r--tex/context/base/mkiv/char-ini.mkiv16
-rw-r--r--tex/context/base/mkiv/char-tex.lua33
-rw-r--r--tex/context/base/mkiv/char-utf.lua13
-rw-r--r--tex/context/base/mkiv/chem-str.lua4
-rw-r--r--tex/context/base/mkiv/chem-str.mkiv12
-rw-r--r--tex/context/base/mkiv/cldf-bas.lua155
-rw-r--r--tex/context/base/mkiv/cldf-ini.lua658
-rw-r--r--tex/context/base/mkiv/cldf-ini.mkiv8
-rw-r--r--tex/context/base/mkiv/cldf-int.lua5
-rw-r--r--tex/context/base/mkiv/cldf-scn.lua7
-rw-r--r--tex/context/base/mkiv/cldf-ver.lua87
-rw-r--r--tex/context/base/mkiv/colo-imp-crayola.mkiv10
-rw-r--r--tex/context/base/mkiv/colo-imp-svg.mkiv164
-rw-r--r--tex/context/base/mkiv/colo-ini.lua66
-rw-r--r--tex/context/base/mkiv/colo-ini.mkiv19
-rw-r--r--tex/context/base/mkiv/colo-run.lua2
-rw-r--r--tex/context/base/mkiv/cont-log.mkiv40
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv18
-rw-r--r--tex/context/base/mkiv/cont-run.lua48
-rw-r--r--tex/context/base/mkiv/cont-run.mkiv20
-rw-r--r--tex/context/base/mkiv/context.mkiv62
-rw-r--r--tex/context/base/mkiv/core-con.lua393
-rw-r--r--tex/context/base/mkiv/core-con.mkiv212
-rw-r--r--tex/context/base/mkiv/core-dat.lua62
-rw-r--r--tex/context/base/mkiv/core-dat.mkiv33
-rw-r--r--tex/context/base/mkiv/core-def.mkiv2
-rw-r--r--tex/context/base/mkiv/core-env.lua67
-rw-r--r--tex/context/base/mkiv/core-env.mkiv46
-rw-r--r--tex/context/base/mkiv/core-lmt.lua34
-rw-r--r--tex/context/base/mkiv/core-lmt.mkiv32
-rw-r--r--tex/context/base/mkiv/core-sys.lua8
-rw-r--r--tex/context/base/mkiv/core-two.lua93
-rw-r--r--tex/context/base/mkiv/core-two.mkiv8
-rw-r--r--tex/context/base/mkiv/core-uti.lua23
-rw-r--r--tex/context/base/mkiv/data-aux.lua2
-rw-r--r--tex/context/base/mkiv/data-pre.lua26
-rw-r--r--tex/context/base/mkiv/data-res.lua6
-rw-r--r--tex/context/base/mkiv/data-tex.lua8
-rw-r--r--tex/context/base/mkiv/data-tre.lua5
-rw-r--r--tex/context/base/mkiv/data-use.lua6
-rw-r--r--tex/context/base/mkiv/data-zip.lua10
-rw-r--r--tex/context/base/mkiv/driv-ini.lua194
-rw-r--r--tex/context/base/mkiv/driv-ini.mkiv25
-rw-r--r--tex/context/base/mkiv/export-example.css37
-rw-r--r--tex/context/base/mkiv/file-job.lua3
-rw-r--r--tex/context/base/mkiv/file-job.mkvi19
-rw-r--r--tex/context/base/mkiv/file-mod.mkvi32
-rw-r--r--tex/context/base/mkiv/font-aux.lua1
-rw-r--r--tex/context/base/mkiv/font-cff.lua554
-rw-r--r--tex/context/base/mkiv/font-cft.lua10
-rw-r--r--tex/context/base/mkiv/font-chk.lua94
-rw-r--r--tex/context/base/mkiv/font-col.lua191
-rw-r--r--tex/context/base/mkiv/font-col.mkvi5
-rw-r--r--tex/context/base/mkiv/font-con.lua179
-rw-r--r--tex/context/base/mkiv/font-ctx.lua585
-rw-r--r--tex/context/base/mkiv/font-def.lua120
-rw-r--r--tex/context/base/mkiv/font-dsp.lua736
-rw-r--r--tex/context/base/mkiv/font-emp.mkvi22
-rw-r--r--tex/context/base/mkiv/font-enh.lua16
-rw-r--r--tex/context/base/mkiv/font-ext.lua1856
-rw-r--r--tex/context/base/mkiv/font-fbk.lua272
-rw-r--r--tex/context/base/mkiv/font-fea.mkvi10
-rw-r--r--tex/context/base/mkiv/font-fil.mkvi33
-rw-r--r--tex/context/base/mkiv/font-gbn.lua262
-rw-r--r--tex/context/base/mkiv/font-gds.mkvi2
-rw-r--r--tex/context/base/mkiv/font-hsh.lua101
-rw-r--r--tex/context/base/mkiv/font-imp-dimensions.lua115
-rw-r--r--tex/context/base/mkiv/font-imp-effects.lua414
-rw-r--r--tex/context/base/mkiv/font-imp-italics.lua147
-rw-r--r--tex/context/base/mkiv/font-imp-ligatures.lua136
-rw-r--r--tex/context/base/mkiv/font-imp-math.lua81
-rw-r--r--tex/context/base/mkiv/font-imp-notused.lua168
-rw-r--r--tex/context/base/mkiv/font-imp-properties.lua130
-rw-r--r--tex/context/base/mkiv/font-imp-quality.lua527
-rw-r--r--tex/context/base/mkiv/font-imp-reorder.lua174
-rw-r--r--tex/context/base/mkiv/font-imp-tex.lua144
-rw-r--r--tex/context/base/mkiv/font-imp-tracing.lua281
-rw-r--r--tex/context/base/mkiv/font-imp-unicode.lua82
-rw-r--r--tex/context/base/mkiv/font-ini.lua47
-rw-r--r--tex/context/base/mkiv/font-ini.mkvi99
-rw-r--r--tex/context/base/mkiv/font-lib.mkvi43
-rw-r--r--tex/context/base/mkiv/font-map.lua160
-rw-r--r--tex/context/base/mkiv/font-mat.mkvi30
-rw-r--r--tex/context/base/mkiv/font-mis.lua14
-rw-r--r--tex/context/base/mkiv/font-mps.lua131
-rw-r--r--tex/context/base/mkiv/font-nod.lua187
-rw-r--r--tex/context/base/mkiv/font-ocl.lua349
-rw-r--r--tex/context/base/mkiv/font-one.lua15
-rw-r--r--tex/context/base/mkiv/font-onr.lua79
-rw-r--r--tex/context/base/mkiv/font-osd.lua121
-rw-r--r--tex/context/base/mkiv/font-ota.lua10
-rw-r--r--tex/context/base/mkiv/font-otc.lua322
-rw-r--r--tex/context/base/mkiv/font-otj.lua110
-rw-r--r--tex/context/base/mkiv/font-otl.lua41
-rw-r--r--tex/context/base/mkiv/font-oto.lua69
-rw-r--r--tex/context/base/mkiv/font-otr.lua275
-rw-r--r--tex/context/base/mkiv/font-ots.lua500
-rw-r--r--tex/context/base/mkiv/font-ott.lua50
-rw-r--r--tex/context/base/mkiv/font-oup.lua644
-rw-r--r--tex/context/base/mkiv/font-pre.mkiv49
-rw-r--r--tex/context/base/mkiv/font-prv.lua78
-rw-r--r--tex/context/base/mkiv/font-sel.lua149
-rw-r--r--tex/context/base/mkiv/font-set.mkvi6
-rw-r--r--tex/context/base/mkiv/font-shp.lua128
-rw-r--r--tex/context/base/mkiv/font-sol.lua128
-rw-r--r--tex/context/base/mkiv/font-sty.mkvi25
-rw-r--r--tex/context/base/mkiv/font-sym.mkvi2
-rw-r--r--tex/context/base/mkiv/font-syn.lua5
-rw-r--r--tex/context/base/mkiv/font-tfm.lua448
-rw-r--r--tex/context/base/mkiv/font-tra.mkiv2
-rw-r--r--tex/context/base/mkiv/font-ttf.lua465
-rw-r--r--tex/context/base/mkiv/font-var.mkvi2
-rw-r--r--tex/context/base/mkiv/font-vfc.lua123
-rw-r--r--tex/context/base/mkiv/font-vir.lua23
-rw-r--r--tex/context/base/mkiv/font-web.lua20
-rw-r--r--tex/context/base/mkiv/font-xtx.lua97
-rw-r--r--tex/context/base/mkiv/good-ctx.lua84
-rw-r--r--tex/context/base/mkiv/grph-epd.lua20
-rw-r--r--tex/context/base/mkiv/grph-inc.lua286
-rw-r--r--tex/context/base/mkiv/grph-inc.mkiv101
-rw-r--r--tex/context/base/mkiv/grph-mem.lua164
-rw-r--r--tex/context/base/mkiv/grph-pat.lua4
-rw-r--r--tex/context/base/mkiv/grph-rul.lua149
-rw-r--r--tex/context/base/mkiv/grph-swf.lua3
-rw-r--r--tex/context/base/mkiv/grph-trf.mkiv39
-rw-r--r--tex/context/base/mkiv/java-imp-example.mkiv (renamed from tex/context/base/mkiv/java-imp-exa.mkiv)5
-rw-r--r--tex/context/base/mkiv/java-imp-fields.mkiv (renamed from tex/context/base/mkiv/java-imp-fld.mkiv)47
-rw-r--r--tex/context/base/mkiv/java-imp-highlight.mkiv (renamed from tex/context/base/mkiv/java-imp-rhh.mkiv)2
-rw-r--r--tex/context/base/mkiv/java-imp-print.mkiv (renamed from tex/context/base/mkiv/java-imp-fil.mkiv)4
-rw-r--r--tex/context/base/mkiv/java-imp-steps.mkiv (renamed from tex/context/base/mkiv/java-imp-stp.mkiv)2
-rw-r--r--tex/context/base/mkiv/java-imp-videoplayer.mkiv82
-rw-r--r--tex/context/base/mkiv/java-imp-vplayer.mkiv105
-rw-r--r--tex/context/base/mkiv/java-ini.lua8
-rw-r--r--tex/context/base/mkiv/java-ini.mkiv17
-rw-r--r--tex/context/base/mkiv/l-bit32.lua10
-rw-r--r--tex/context/base/mkiv/l-dir.lua82
-rw-r--r--tex/context/base/mkiv/l-file.lua38
-rw-r--r--tex/context/base/mkiv/l-lpeg.lua195
-rw-r--r--tex/context/base/mkiv/l-lua.lua40
-rw-r--r--tex/context/base/mkiv/l-macro-imp-optimize.lua29
-rw-r--r--tex/context/base/mkiv/l-macro.lua95
-rw-r--r--tex/context/base/mkiv/l-number.lua23
-rw-r--r--tex/context/base/mkiv/l-os.lua132
-rw-r--r--tex/context/base/mkiv/l-package.lua4
-rw-r--r--tex/context/base/mkiv/l-sandbox.lua3
-rw-r--r--tex/context/base/mkiv/l-sha.lua27
-rw-r--r--tex/context/base/mkiv/l-table.lua132
-rw-r--r--tex/context/base/mkiv/l-unicode.lua228
-rw-r--r--tex/context/base/mkiv/lang-def.lua9
-rw-r--r--tex/context/base/mkiv/lang-def.mkiv44
-rw-r--r--tex/context/base/mkiv/lang-dis.lua107
-rw-r--r--tex/context/base/mkiv/lang-exp.lua36
-rw-r--r--tex/context/base/mkiv/lang-hyp.lua68
-rw-r--r--tex/context/base/mkiv/lang-hyp.mkiv9
-rw-r--r--tex/context/base/mkiv/lang-ini.mkiv270
-rw-r--r--tex/context/base/mkiv/lang-lab.mkiv12
-rw-r--r--tex/context/base/mkiv/lang-mis.mkiv156
-rw-r--r--tex/context/base/mkiv/lang-rep.lua7
-rw-r--r--tex/context/base/mkiv/lang-spa.mkiv18
-rw-r--r--tex/context/base/mkiv/lang-txt.lua102
-rw-r--r--tex/context/base/mkiv/lang-url.lua22
-rw-r--r--tex/context/base/mkiv/lang-wrd.lua16
-rw-r--r--tex/context/base/mkiv/lpdf-ano.lua276
-rw-r--r--tex/context/base/mkiv/lpdf-aux.lua152
-rw-r--r--tex/context/base/mkiv/lpdf-col.lua47
-rw-r--r--tex/context/base/mkiv/lpdf-epa.lua783
-rw-r--r--tex/context/base/mkiv/lpdf-epd.lua518
-rw-r--r--tex/context/base/mkiv/lpdf-fld.lua180
-rw-r--r--tex/context/base/mkiv/lpdf-fmt.lua21
-rw-r--r--tex/context/base/mkiv/lpdf-fnt.lua202
-rw-r--r--tex/context/base/mkiv/lpdf-grp.lua72
-rw-r--r--tex/context/base/mkiv/lpdf-ini.lua1297
-rw-r--r--tex/context/base/mkiv/lpdf-mis.lua126
-rw-r--r--tex/context/base/mkiv/lpdf-nod.lua214
-rw-r--r--tex/context/base/mkiv/lpdf-pda.xml85
-rw-r--r--tex/context/base/mkiv/lpdf-pde.lua1157
-rw-r--r--tex/context/base/mkiv/lpdf-pdx.xml1
-rw-r--r--tex/context/base/mkiv/lpdf-pua.xml41
-rw-r--r--tex/context/base/mkiv/lpdf-ren.lua12
-rw-r--r--tex/context/base/mkiv/lpdf-res.lua26
-rw-r--r--tex/context/base/mkiv/lpdf-swf.lua46
-rw-r--r--tex/context/base/mkiv/lpdf-tag.lua244
-rw-r--r--tex/context/base/mkiv/lpdf-u3d.lua26
-rw-r--r--tex/context/base/mkiv/lpdf-wid.lua40
-rw-r--r--tex/context/base/mkiv/lpdf-xmp.lua75
-rw-r--r--tex/context/base/mkiv/luat-bas.mkiv2
-rw-r--r--tex/context/base/mkiv/luat-cbk.lua6
-rw-r--r--tex/context/base/mkiv/luat-cnf.lua4
-rw-r--r--tex/context/base/mkiv/luat-cod.lua64
-rw-r--r--tex/context/base/mkiv/luat-env.lua24
-rw-r--r--tex/context/base/mkiv/luat-fio.lua4
-rw-r--r--tex/context/base/mkiv/luat-fmt.lua14
-rw-r--r--tex/context/base/mkiv/luat-ini.lua16
-rw-r--r--tex/context/base/mkiv/luat-ini.mkiv127
-rw-r--r--tex/context/base/mkiv/luat-lib.mkiv16
-rw-r--r--tex/context/base/mkiv/luat-run.lua111
-rw-r--r--tex/context/base/mkiv/luat-soc.lua11
-rw-r--r--tex/context/base/mkiv/luat-soc.mkiv52
-rw-r--r--tex/context/base/mkiv/luat-sto.lua2
-rw-r--r--tex/context/base/mkiv/luat-usr.lua3
-rw-r--r--tex/context/base/mkiv/luat-usr.mkiv4
-rw-r--r--tex/context/base/mkiv/lxml-aux.lua25
-rw-r--r--tex/context/base/mkiv/lxml-css.lua137
-rw-r--r--tex/context/base/mkiv/lxml-inf.lua3
-rw-r--r--tex/context/base/mkiv/lxml-ini.mkiv21
-rw-r--r--tex/context/base/mkiv/lxml-lpt.lua276
-rw-r--r--tex/context/base/mkiv/lxml-tex.lua426
-rw-r--r--tex/context/base/mkiv/m-fonts-plugins.mkiv5
-rw-r--r--tex/context/base/mkiv/math-act.lua44
-rw-r--r--tex/context/base/mkiv/math-ali.mkiv29
-rw-r--r--tex/context/base/mkiv/math-arr.mkiv57
-rw-r--r--tex/context/base/mkiv/math-dim.lua3
-rw-r--r--tex/context/base/mkiv/math-dir.lua30
-rw-r--r--tex/context/base/mkiv/math-ext.lua27
-rw-r--r--tex/context/base/mkiv/math-fbk.lua201
-rw-r--r--tex/context/base/mkiv/math-fen.mkiv120
-rw-r--r--tex/context/base/mkiv/math-frc.lua4
-rw-r--r--tex/context/base/mkiv/math-frc.mkiv42
-rw-r--r--tex/context/base/mkiv/math-inc.lua87
-rw-r--r--tex/context/base/mkiv/math-inc.mkiv69
-rw-r--r--tex/context/base/mkiv/math-ini.lua9
-rw-r--r--tex/context/base/mkiv/math-ini.mkiv146
-rw-r--r--tex/context/base/mkiv/math-noa.lua742
-rw-r--r--tex/context/base/mkiv/math-pln.mkiv2
-rw-r--r--tex/context/base/mkiv/math-spa.lua37
-rw-r--r--tex/context/base/mkiv/math-stc.mkvi14
-rw-r--r--tex/context/base/mkiv/math-tag.lua437
-rw-r--r--tex/context/base/mkiv/math-vfu.lua344
-rw-r--r--tex/context/base/mkiv/meta-blb.lua322
-rw-r--r--tex/context/base/mkiv/meta-blb.mkiv56
-rw-r--r--tex/context/base/mkiv/meta-fnt.lua24
-rw-r--r--tex/context/base/mkiv/meta-imp-dum.mkiv4
-rw-r--r--tex/context/base/mkiv/meta-imp-mat.mkiv38
-rw-r--r--tex/context/base/mkiv/meta-imp-txt.mkiv76
-rw-r--r--tex/context/base/mkiv/meta-ini.lua8
-rw-r--r--tex/context/base/mkiv/meta-ini.mkiv57
-rw-r--r--tex/context/base/mkiv/meta-nod.lua81
-rw-r--r--tex/context/base/mkiv/meta-nod.mkiv31
-rw-r--r--tex/context/base/mkiv/meta-pdf.lua76
-rw-r--r--tex/context/base/mkiv/meta-pdh.mkiv24
-rw-r--r--tex/context/base/mkiv/meta-tex.lua6
-rw-r--r--tex/context/base/mkiv/metatex.tex30
-rw-r--r--tex/context/base/mkiv/mlib-ctx.lua87
-rw-r--r--tex/context/base/mkiv/mlib-int.lua191
-rw-r--r--tex/context/base/mkiv/mlib-lua.lua1175
-rw-r--r--tex/context/base/mkiv/mlib-pdf.lua598
-rw-r--r--tex/context/base/mkiv/mlib-pdf.mkiv30
-rw-r--r--tex/context/base/mkiv/mlib-pps.lua1151
-rw-r--r--tex/context/base/mkiv/mlib-pps.mkiv35
-rw-r--r--tex/context/base/mkiv/mlib-run.lua279
-rw-r--r--tex/context/base/mkiv/mtx-context-domotica.tex31
-rw-r--r--tex/context/base/mkiv/mtx-context-fonts.tex98
-rw-r--r--tex/context/base/mkiv/mtx-context-listing.tex4
-rw-r--r--tex/context/base/mkiv/mtx-context-xml.tex5
-rw-r--r--tex/context/base/mkiv/mult-aux.mkiv562
-rw-r--r--tex/context/base/mkiv/mult-def.lua33
-rw-r--r--tex/context/base/mkiv/mult-fun.lua34
-rw-r--r--tex/context/base/mkiv/mult-ini.lua16
-rw-r--r--tex/context/base/mkiv/mult-ini.mkiv15
-rw-r--r--tex/context/base/mkiv/mult-low.lua58
-rw-r--r--tex/context/base/mkiv/mult-prm.lua32
-rw-r--r--tex/context/base/mkiv/mult-prm.mkiv3
-rw-r--r--tex/context/base/mkiv/mult-sys.mkiv2
-rw-r--r--tex/context/base/mkiv/node-acc.lua72
-rw-r--r--tex/context/base/mkiv/node-aux.lua198
-rw-r--r--tex/context/base/mkiv/node-bck.lua378
-rw-r--r--tex/context/base/mkiv/node-bck.mkiv21
-rw-r--r--tex/context/base/mkiv/node-dir.lua359
-rw-r--r--tex/context/base/mkiv/node-fin.lua472
-rw-r--r--tex/context/base/mkiv/node-fin.mkiv4
-rw-r--r--tex/context/base/mkiv/node-fnt.lua545
-rw-r--r--tex/context/base/mkiv/node-ini.lua146
-rw-r--r--tex/context/base/mkiv/node-ini.mkiv4
-rw-r--r--tex/context/base/mkiv/node-ltp.lua3261
-rw-r--r--tex/context/base/mkiv/node-met.lua172
-rw-r--r--tex/context/base/mkiv/node-mig.lua6
-rw-r--r--tex/context/base/mkiv/node-nut.lua327
-rw-r--r--tex/context/base/mkiv/node-par.lua48
-rw-r--r--tex/context/base/mkiv/node-ppt.lua173
-rw-r--r--tex/context/base/mkiv/node-pro.lua137
-rw-r--r--tex/context/base/mkiv/node-ref.lua291
-rw-r--r--tex/context/base/mkiv/node-res.lua329
-rw-r--r--tex/context/base/mkiv/node-rul.lua374
-rw-r--r--tex/context/base/mkiv/node-rul.mkiv39
-rw-r--r--tex/context/base/mkiv/node-scn.lua31
-rw-r--r--tex/context/base/mkiv/node-ser.lua8
-rw-r--r--tex/context/base/mkiv/node-shp.lua86
-rw-r--r--tex/context/base/mkiv/node-syn.lua109
-rw-r--r--tex/context/base/mkiv/node-tex.lua45
-rw-r--r--tex/context/base/mkiv/node-tra.lua256
-rw-r--r--tex/context/base/mkiv/node-tsk.lua609
-rw-r--r--tex/context/base/mkiv/node-tst.lua10
-rw-r--r--tex/context/base/mkiv/pack-bar.mkiv6
-rw-r--r--tex/context/base/mkiv/pack-bck.mkvi48
-rw-r--r--tex/context/base/mkiv/pack-box.mkiv1
-rw-r--r--tex/context/base/mkiv/pack-com.mkiv18
-rw-r--r--tex/context/base/mkiv/pack-cut.mkiv78
-rw-r--r--tex/context/base/mkiv/pack-lyr.mkiv86
-rw-r--r--tex/context/base/mkiv/pack-mrl.mkiv83
-rw-r--r--tex/context/base/mkiv/pack-obj.lua43
-rw-r--r--tex/context/base/mkiv/pack-obj.mkiv14
-rw-r--r--tex/context/base/mkiv/pack-rul.lua159
-rw-r--r--tex/context/base/mkiv/pack-rul.mkiv190
-rw-r--r--tex/context/base/mkiv/page-bck.mkiv2
-rw-r--r--tex/context/base/mkiv/page-box.mkvi23
-rw-r--r--tex/context/base/mkiv/page-cst.lua161
-rw-r--r--tex/context/base/mkiv/page-cst.mkiv5
-rw-r--r--tex/context/base/mkiv/page-ffl.mkiv39
-rw-r--r--tex/context/base/mkiv/page-flt.mkiv10
-rw-r--r--tex/context/base/mkiv/page-imp.mkiv92
-rw-r--r--tex/context/base/mkiv/page-inf.mkiv8
-rw-r--r--tex/context/base/mkiv/page-ini.lua43
-rw-r--r--tex/context/base/mkiv/page-ini.mkiv7
-rw-r--r--tex/context/base/mkiv/page-inj.mkvi2
-rw-r--r--tex/context/base/mkiv/page-lay.mkiv157
-rw-r--r--tex/context/base/mkiv/page-lin.lua44
-rw-r--r--tex/context/base/mkiv/page-lin.mkvi10
-rw-r--r--tex/context/base/mkiv/page-mix.lua19
-rw-r--r--tex/context/base/mkiv/page-mix.mkiv27
-rw-r--r--tex/context/base/mkiv/page-mul.mkiv36
-rw-r--r--tex/context/base/mkiv/page-one.mkiv63
-rw-r--r--tex/context/base/mkiv/page-otr.mkvi14
-rw-r--r--tex/context/base/mkiv/page-pcl.mkiv79
-rw-r--r--tex/context/base/mkiv/page-run.mkiv7
-rw-r--r--tex/context/base/mkiv/page-sel.mkvi4
-rw-r--r--tex/context/base/mkiv/page-set.mkiv67
-rw-r--r--tex/context/base/mkiv/page-sid.mkiv153
-rw-r--r--tex/context/base/mkiv/page-smp.mkiv59
-rw-r--r--tex/context/base/mkiv/page-spr.mkiv35
-rw-r--r--tex/context/base/mkiv/page-str.lua73
-rw-r--r--tex/context/base/mkiv/page-str.mkiv2
-rw-r--r--tex/context/base/mkiv/page-txt.mkvi33
-rw-r--r--tex/context/base/mkiv/publ-aut.lua48
-rw-r--r--tex/context/base/mkiv/publ-dat.lua123
-rw-r--r--tex/context/base/mkiv/publ-imp-apa.mkvi87
-rw-r--r--tex/context/base/mkiv/publ-imp-cite.mkvi3
-rw-r--r--tex/context/base/mkiv/publ-inc.lua26
-rw-r--r--tex/context/base/mkiv/publ-inc.mkiv63
-rw-r--r--tex/context/base/mkiv/publ-ini.lua43
-rw-r--r--tex/context/base/mkiv/publ-ini.mkiv75
-rw-r--r--tex/context/base/mkiv/scrn-bar.mkvi2
-rw-r--r--tex/context/base/mkiv/scrn-but.mkvi19
-rw-r--r--tex/context/base/mkiv/scrn-fld.mkvi106
-rw-r--r--tex/context/base/mkiv/scrn-ini.mkvi2
-rw-r--r--tex/context/base/mkiv/scrn-pag.mkvi20
-rw-r--r--tex/context/base/mkiv/scrn-ref.mkvi18
-rw-r--r--tex/context/base/mkiv/scrn-wid.mkvi97
-rw-r--r--tex/context/base/mkiv/scrp-cjk.lua107
-rw-r--r--tex/context/base/mkiv/scrp-eth.lua86
-rw-r--r--tex/context/base/mkiv/scrp-ini.lua247
-rw-r--r--tex/context/base/mkiv/scrp-ini.mkiv23
-rw-r--r--tex/context/base/mkiv/scrp-tib.lua81
-rw-r--r--tex/context/base/mkiv/sort-ini.lua29
-rw-r--r--tex/context/base/mkiv/sort-lan.lua46
-rw-r--r--tex/context/base/mkiv/spac-adj.lua67
-rw-r--r--tex/context/base/mkiv/spac-adj.mkiv51
-rw-r--r--tex/context/base/mkiv/spac-ali.lua16
-rw-r--r--tex/context/base/mkiv/spac-ali.mkiv134
-rw-r--r--tex/context/base/mkiv/spac-chr.lua100
-rw-r--r--tex/context/base/mkiv/spac-chr.mkiv2
-rw-r--r--tex/context/base/mkiv/spac-flr.mkiv34
-rw-r--r--tex/context/base/mkiv/spac-grd.mkiv4
-rw-r--r--tex/context/base/mkiv/spac-hor.mkiv56
-rw-r--r--tex/context/base/mkiv/spac-lin.mkiv4
-rw-r--r--tex/context/base/mkiv/spac-pag.mkiv5
-rw-r--r--tex/context/base/mkiv/spac-par.mkiv14
-rw-r--r--tex/context/base/mkiv/spac-prf.lua27
-rw-r--r--tex/context/base/mkiv/spac-ver.lua421
-rw-r--r--tex/context/base/mkiv/spac-ver.mkiv186
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin26054 -> 26589 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin255106 -> 268348 bytes
-rw-r--r--tex/context/base/mkiv/strc-blk.lua92
-rw-r--r--tex/context/base/mkiv/strc-blk.mkiv128
-rw-r--r--tex/context/base/mkiv/strc-con.mkvi18
-rw-r--r--tex/context/base/mkiv/strc-def.mkiv11
-rw-r--r--tex/context/base/mkiv/strc-doc.lua138
-rw-r--r--tex/context/base/mkiv/strc-doc.mkiv27
-rw-r--r--tex/context/base/mkiv/strc-flt.lua34
-rw-r--r--tex/context/base/mkiv/strc-flt.mkvi312
-rw-r--r--tex/context/base/mkiv/strc-itm.mkvi4
-rw-r--r--tex/context/base/mkiv/strc-lnt.mkvi6
-rw-r--r--tex/context/base/mkiv/strc-lst.lua37
-rw-r--r--tex/context/base/mkiv/strc-lst.mkvi17
-rw-r--r--tex/context/base/mkiv/strc-mar.lua180
-rw-r--r--tex/context/base/mkiv/strc-mat.mkiv16
-rw-r--r--tex/context/base/mkiv/strc-not.lua39
-rw-r--r--tex/context/base/mkiv/strc-not.mkvi55
-rw-r--r--tex/context/base/mkiv/strc-num.lua27
-rw-r--r--tex/context/base/mkiv/strc-num.mkiv16
-rw-r--r--tex/context/base/mkiv/strc-pag.lua16
-rw-r--r--tex/context/base/mkiv/strc-pag.mkiv29
-rw-r--r--tex/context/base/mkiv/strc-ref.lua102
-rw-r--r--tex/context/base/mkiv/strc-ref.mkvi502
-rw-r--r--tex/context/base/mkiv/strc-reg.lua407
-rw-r--r--tex/context/base/mkiv/strc-reg.mkiv232
-rw-r--r--tex/context/base/mkiv/strc-ren.mkiv46
-rw-r--r--tex/context/base/mkiv/strc-sbe.mkiv4
-rw-r--r--tex/context/base/mkiv/strc-sec.mkiv107
-rw-r--r--tex/context/base/mkiv/strc-syn.mkiv4
-rw-r--r--tex/context/base/mkiv/strc-tag.lua106
-rw-r--r--tex/context/base/mkiv/strc-tag.mkiv108
-rw-r--r--tex/context/base/mkiv/strc-usr.lua29
-rw-r--r--tex/context/base/mkiv/strc-usr.mkiv180
-rw-r--r--tex/context/base/mkiv/supp-box.lua236
-rw-r--r--tex/context/base/mkiv/supp-box.mkiv182
-rw-r--r--tex/context/base/mkiv/supp-dir.mkiv56
-rw-r--r--tex/context/base/mkiv/supp-mat.mkiv2
-rw-r--r--tex/context/base/mkiv/symb-emj.lua27
-rw-r--r--tex/context/base/mkiv/symb-imp-fontawesome.mkiv1505
-rw-r--r--tex/context/base/mkiv/symb-imp-mis.mkiv23
-rw-r--r--tex/context/base/mkiv/symb-imp-mvs.mkiv18
-rw-r--r--tex/context/base/mkiv/symb-ini.mkiv76
-rw-r--r--tex/context/base/mkiv/symb-run.mkiv62
-rw-r--r--tex/context/base/mkiv/syst-aux.lua133
-rw-r--r--tex/context/base/mkiv/syst-aux.mkiv1521
-rw-r--r--tex/context/base/mkiv/syst-cmp.lua8
-rw-r--r--tex/context/base/mkiv/syst-cmp.mkiv22
-rw-r--r--tex/context/base/mkiv/syst-ini.mkiv643
-rw-r--r--tex/context/base/mkiv/syst-lua.lua11
-rw-r--r--tex/context/base/mkiv/syst-lua.mkiv36
-rw-r--r--tex/context/base/mkiv/syst-rtp.mkiv (renamed from tex/context/base/mkii/syst-rtp.mkiv)0
-rw-r--r--tex/context/base/mkiv/tabl-com.mkiv64
-rw-r--r--tex/context/base/mkiv/tabl-ltb.mkiv8
-rw-r--r--tex/context/base/mkiv/tabl-ntb.mkiv100
-rw-r--r--tex/context/base/mkiv/tabl-tab.mkiv38
-rw-r--r--tex/context/base/mkiv/tabl-tbl.mkiv463
-rw-r--r--tex/context/base/mkiv/tabl-tsp.mkiv29
-rw-r--r--tex/context/base/mkiv/tabl-xtb.lua13
-rw-r--r--tex/context/base/mkiv/tabl-xtb.mkvi149
-rw-r--r--tex/context/base/mkiv/task-ini.lua345
-rw-r--r--tex/context/base/mkiv/toks-aux.mkiv51
-rw-r--r--tex/context/base/mkiv/toks-ini.lua115
-rw-r--r--tex/context/base/mkiv/toks-ini.mkiv5
-rw-r--r--tex/context/base/mkiv/toks-scn.lua70
-rw-r--r--tex/context/base/mkiv/toks-scn.mkiv22
-rw-r--r--tex/context/base/mkiv/trac-deb.lua41
-rw-r--r--tex/context/base/mkiv/trac-inf.lua42
-rw-r--r--tex/context/base/mkiv/trac-jus.lua10
-rw-r--r--tex/context/base/mkiv/trac-log.lua63
-rw-r--r--tex/context/base/mkiv/trac-par.lua29
-rw-r--r--tex/context/base/mkiv/trac-set.lua17
-rw-r--r--tex/context/base/mkiv/trac-vis.lua366
-rw-r--r--tex/context/base/mkiv/trac-vis.mkiv7
-rw-r--r--tex/context/base/mkiv/type-ini.mkvi90
-rw-r--r--tex/context/base/mkiv/type-set.mkiv2
-rw-r--r--tex/context/base/mkiv/typo-bld.lua61
-rw-r--r--tex/context/base/mkiv/typo-brk.lua30
-rw-r--r--tex/context/base/mkiv/typo-cap.lua173
-rw-r--r--tex/context/base/mkiv/typo-cap.mkiv62
-rw-r--r--tex/context/base/mkiv/typo-chr.lua205
-rw-r--r--tex/context/base/mkiv/typo-chr.mkiv19
-rw-r--r--tex/context/base/mkiv/typo-cln.lua12
-rw-r--r--tex/context/base/mkiv/typo-del.mkiv118
-rw-r--r--tex/context/base/mkiv/typo-dha.lua58
-rw-r--r--tex/context/base/mkiv/typo-dig.lua20
-rw-r--r--tex/context/base/mkiv/typo-dir.lua17
-rw-r--r--tex/context/base/mkiv/typo-dir.mkiv190
-rw-r--r--tex/context/base/mkiv/typo-drp.lua45
-rw-r--r--tex/context/base/mkiv/typo-drp.mkiv2
-rw-r--r--tex/context/base/mkiv/typo-dua.lua144
-rw-r--r--tex/context/base/mkiv/typo-dub.lua271
-rw-r--r--tex/context/base/mkiv/typo-duc.lua278
-rw-r--r--tex/context/base/mkiv/typo-fkr.lua17
-rw-r--r--tex/context/base/mkiv/typo-fln.lua64
-rw-r--r--tex/context/base/mkiv/typo-fln.mkiv2
-rw-r--r--tex/context/base/mkiv/typo-itc.lua69
-rw-r--r--tex/context/base/mkiv/typo-krn.lua314
-rw-r--r--tex/context/base/mkiv/typo-lin.lua93
-rw-r--r--tex/context/base/mkiv/typo-mar.lua83
-rw-r--r--tex/context/base/mkiv/typo-mar.mkiv12
-rw-r--r--tex/context/base/mkiv/typo-pag.lua5
-rw-r--r--tex/context/base/mkiv/typo-par.mkiv2
-rw-r--r--tex/context/base/mkiv/typo-pnc.lua21
-rw-r--r--tex/context/base/mkiv/typo-rep.lua10
-rw-r--r--tex/context/base/mkiv/typo-rub.lua42
-rw-r--r--tex/context/base/mkiv/typo-rub.mkiv9
-rw-r--r--tex/context/base/mkiv/typo-scr.mkiv6
-rw-r--r--tex/context/base/mkiv/typo-spa.lua12
-rw-r--r--tex/context/base/mkiv/typo-sus.lua9
-rw-r--r--tex/context/base/mkiv/typo-tal.lua37
-rw-r--r--tex/context/base/mkiv/typo-wrp.lua85
-rw-r--r--tex/context/base/mkiv/typo-wrp.mkiv9
-rw-r--r--tex/context/base/mkiv/util-deb.lua83
-rw-r--r--tex/context/base/mkiv/util-env.lua45
-rw-r--r--tex/context/base/mkiv/util-evo.lua109
-rw-r--r--tex/context/base/mkiv/util-fil.lua66
-rw-r--r--tex/context/base/mkiv/util-fmt.lua11
-rw-r--r--tex/context/base/mkiv/util-jsn.lua95
-rw-r--r--tex/context/base/mkiv/util-lib.lua62
-rw-r--r--tex/context/base/mkiv/util-lua.lua7
-rw-r--r--tex/context/base/mkiv/util-mrg.lua1
-rw-r--r--tex/context/base/mkiv/util-prs.lua35
-rw-r--r--tex/context/base/mkiv/util-sac.lua113
-rw-r--r--tex/context/base/mkiv/util-seq.lua370
-rw-r--r--tex/context/base/mkiv/util-sha.lua35
-rw-r--r--tex/context/base/mkiv/util-soc-imp-copas.lua931
-rw-r--r--tex/context/base/mkiv/util-soc-imp-ftp.lua402
-rw-r--r--tex/context/base/mkiv/util-soc-imp-headers.lua145
-rw-r--r--tex/context/base/mkiv/util-soc-imp-http.lua436
-rw-r--r--tex/context/base/mkiv/util-soc-imp-ltn12.lua387
-rw-r--r--tex/context/base/mkiv/util-soc-imp-mime.lua104
-rw-r--r--tex/context/base/mkiv/util-soc-imp-reset.lua13
-rw-r--r--tex/context/base/mkiv/util-soc-imp-smtp.lua267
-rw-r--r--tex/context/base/mkiv/util-soc-imp-socket.lua193
-rw-r--r--tex/context/base/mkiv/util-soc-imp-tp.lua144
-rw-r--r--tex/context/base/mkiv/util-soc-imp-url.lua268
-rw-r--r--tex/context/base/mkiv/util-soc.lua32
-rw-r--r--tex/context/base/mkiv/util-sql-imp-ffi.lua590
-rw-r--r--tex/context/base/mkiv/util-sql-imp-library.lua8
-rw-r--r--tex/context/base/mkiv/util-sql-imp-sqlite.lua13
-rw-r--r--tex/context/base/mkiv/util-sql-logins.lua12
-rw-r--r--tex/context/base/mkiv/util-sql-users.lua10
-rw-r--r--tex/context/base/mkiv/util-sta.lua14
-rw-r--r--tex/context/base/mkiv/util-sto.lua13
-rw-r--r--tex/context/base/mkiv/util-str.lua526
-rw-r--r--tex/context/base/mkiv/util-tab.lua54
-rw-r--r--tex/context/base/mkiv/util-you.lua1
566 files changed, 49700 insertions, 25986 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index 494992502..a688bc4b4 100644
--- a/tex/context/base/mkii/cont-new.mkii
+++ b/tex/context/base/mkii/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2018.04.04 00:51}
+\newcontextversion{2019.02.22 19:35}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii
index 293866194..398b6e894 100644
--- a/tex/context/base/mkii/context.mkii
+++ b/tex/context/base/mkii/context.mkii
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2018.04.04 00:51}
+\edef\contextversion{2019.02.22 19:35}
%D For those who want to use this:
diff --git a/tex/context/base/mkii/core-sys.mkii b/tex/context/base/mkii/core-sys.mkii
index 54778eeed..5aa669d2c 100644
--- a/tex/context/base/mkii/core-sys.mkii
+++ b/tex/context/base/mkii/core-sys.mkii
@@ -167,7 +167,7 @@
\def\stoplocal {\dostopglobaldefs}
\def\startglobal {\dostartglobaldefs<+}
\def\stopglobal {\dostopglobaldefs}
-
+
\def\complexstart[#1]{\bgroup\getvalue{\e!start#1}}
\def\complexstop [#1]{\getvalue{\e!stop #1}\egroup}
@@ -215,7 +215,7 @@
\def\setupstartstop
{\dodoubleargument\dosetupstartstop}
-
+
% \docommand kan niet worden gebruikt omdat deze macro
% soms lokaal wordt gebruikt
@@ -275,7 +275,7 @@
\def\docommand##1{\setbox0\hbox{\getvalue{\string##1}##1}}%
\processcommalist[#1]\docommand
\egroup}
-
+
\newif\ifforcefileexpansion % handy for document level overload
%D The next implementation is about 4 times as faster than a
@@ -374,7 +374,7 @@
\let\unicodechar\numbertoutf
\edef\ascii{#1}%
\expandafter\endgroup\expandafter\edef\expandafter#2\expandafter{\ascii}}
-
+
% \setvalue{statevalue\v!stop }{0}
% \setvalue{statevalue\v!start }{1}
% \setvalue{statevalue\v!normaal}{2}
@@ -385,12 +385,12 @@
% {\chardef\currentstate=0\getvalue{statevalue\getvalue{#1\c!state}\relax}
%
% \ifcase\currentstate ...
-
+
\def\redo{\dorepeat} % [n*10], kind of obsolete
% obsolete, use \dorecurse instead
%
% \def\herhaler {\repeater}
% \def\herhaalmetcommando {\dorepeatwithcommand}
-
+
\protect \endinput
diff --git a/tex/context/base/mkii/enco-agr.mkii b/tex/context/base/mkii/enco-agr.mkii
index 1dbb9b577..9d821cca1 100644
--- a/tex/context/base/mkii/enco-agr.mkii
+++ b/tex/context/base/mkii/enco-agr.mkii
@@ -17,6 +17,7 @@
\definecasemaps 91 to 255 lc 0 uc 0
\definecaseself 4 % apostrofe
+ \definecaseself 5 % greekbetaalt
\stopmapping
@@ -26,7 +27,7 @@
\definecharacter endash 2
\definecharacter emdash 3
\definecharacter apostrophe 4
-\definecharacter greekaltbeta 5
+\definecharacter greekbetaalt 5
\definecharacter epih 6
\definecharacter textbraceleft 8
diff --git a/tex/context/base/mkii/enco-def.mkii b/tex/context/base/mkii/enco-def.mkii
index 20c885d4d..53a3e9a98 100644
--- a/tex/context/base/mkii/enco-def.mkii
+++ b/tex/context/base/mkii/enco-def.mkii
@@ -505,6 +505,7 @@
\definecharacter greekalpha {\alpha}
\definecharacter greekbeta {\beta}
+\definecharacter greekbetaalt {\beta}
\definecharacter greekgamma {\gamma}
\definecharacter greekdelta {\delta}
\definecharacter greekepsilon {\varepsilon}
diff --git a/tex/context/base/mkii/enco-uc.mkii b/tex/context/base/mkii/enco-uc.mkii
index 0be22318a..f39260b16 100644
--- a/tex/context/base/mkii/enco-uc.mkii
+++ b/tex/context/base/mkii/enco-uc.mkii
@@ -505,6 +505,8 @@
\definecharacter greekupsilondialytikatonos {\uchar3{176}}
% new:
+
+\definecharacter greekbetaalt {\uchar3{208}}
\definecharacter greekthetaalt {\uchar3{209}}
\definecharacter greekphialt {\uchar3{213}}
\definecharacter greekpialt {\uchar3{214}}
diff --git a/tex/context/base/mkii/mult-cs.mkii b/tex/context/base/mkii/mult-cs.mkii
index 9a4cc112b..4ab875e4d 100644
--- a/tex/context/base/mkii/mult-cs.mkii
+++ b/tex/context/base/mkii/mult-cs.mkii
@@ -137,6 +137,7 @@
\setinterfacevariable{chemicals}{chemicals}
\setinterfacevariable{chemistry}{chemistry}
\setinterfacevariable{cite}{cite}
+\setinterfacevariable{closed}{closed}
\setinterfacevariable{color}{barevne}
\setinterfacevariable{column}{column}
\setinterfacevariable{columns}{sloupce}
@@ -418,7 +419,7 @@
\setinterfacevariable{positive}{positiv}
\setinterfacevariable{postponing}{odlozit}
\setinterfacevariable{postscript}{postscript}
-\setinterfacevariable{precedingpage}{followingpage}
+\setinterfacevariable{precedingpage}{precedingpage}
\setinterfacevariable{preference}{nastaveni}
\setinterfacevariable{preview}{nahled}
\setinterfacevariable{previous}{predchozi}
@@ -586,6 +587,7 @@
\setinterfacevariable{understrike}{understrike}
\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unframed}{unframed}
+\setinterfacevariable{unicode}{unicode}
\setinterfacevariable{unit}{jednotka}
\setinterfacevariable{units}{jednotky}
\setinterfacevariable{unknown}{neznamy}
@@ -853,7 +855,7 @@
\setinterfaceconstant{headseparator}{headseparator}
\setinterfaceconstant{headstyle}{stylhlavicky}
\setinterfaceconstant{height}{vyska}
-\setinterfaceconstant{hfactor}{vfaktor}
+\setinterfaceconstant{hfactor}{hfaktor}
\setinterfaceconstant{hfil}{hfil}
\setinterfaceconstant{hidenumber}{hidenumber}
\setinterfaceconstant{hoffset}{hoffset}
@@ -1027,6 +1029,7 @@
\setinterfaceconstant{otherstext}{otherstext}
\setinterfaceconstant{outermargin}{outermargin}
\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownerpassword}{ownerpassword}
\setinterfaceconstant{ownnumber}{vlastnicislo}
\setinterfaceconstant{page}{stranka}
\setinterfaceconstant{pageboundaries}{hranicestranky}
@@ -1240,6 +1243,7 @@
\setinterfaceconstant{textstyle}{styltextu}
\setinterfaceconstant{textwidth}{sirkatextu}
\setinterfaceconstant{threshold}{threshold}
+\setinterfaceconstant{time}{time}
\setinterfaceconstant{title}{titul}
\setinterfaceconstant{titlecolor}{barvatitulek}
\setinterfaceconstant{titlecommand}{titlecommand}
@@ -1268,12 +1272,14 @@
\setinterfaceconstant{up}{up}
\setinterfaceconstant{urlalternative}{urlalternativa}
\setinterfaceconstant{urlspace}{prostorurl}
+\setinterfaceconstant{userpassword}{userpassword}
\setinterfaceconstant{validate}{validovat}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{vprikaz}
\setinterfaceconstant{vcompact}{vcompact}
\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{offsethlavicky}
+\setinterfaceconstant{vfactor}{vfaktor}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{viewerprefix}{viewerprefix}
\setinterfaceconstant{voffset}{voffset}
diff --git a/tex/context/base/mkii/mult-de.mkii b/tex/context/base/mkii/mult-de.mkii
index a5269ff3f..46a239304 100644
--- a/tex/context/base/mkii/mult-de.mkii
+++ b/tex/context/base/mkii/mult-de.mkii
@@ -137,6 +137,7 @@
\setinterfacevariable{chemicals}{chemicals}
\setinterfacevariable{chemistry}{chemistry}
\setinterfacevariable{cite}{cite}
+\setinterfacevariable{closed}{closed}
\setinterfacevariable{color}{farbe}
\setinterfacevariable{column}{column}
\setinterfacevariable{columns}{spalten}
@@ -418,7 +419,7 @@
\setinterfacevariable{positive}{positiv}
\setinterfacevariable{postponing}{verschieben}
\setinterfacevariable{postscript}{postscript}
-\setinterfacevariable{precedingpage}{followingpage}
+\setinterfacevariable{precedingpage}{precedingpage}
\setinterfacevariable{preference}{einstellung}
\setinterfacevariable{preview}{vorschau}
\setinterfacevariable{previous}{vorig}
@@ -586,6 +587,7 @@
\setinterfacevariable{understrike}{understrike}
\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unframed}{unframed}
+\setinterfacevariable{unicode}{unicode}
\setinterfacevariable{unit}{einheit}
\setinterfacevariable{units}{einheiten}
\setinterfacevariable{unknown}{unbekannt}
@@ -1027,6 +1029,7 @@
\setinterfaceconstant{otherstext}{otherstext}
\setinterfaceconstant{outermargin}{outermargin}
\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownerpassword}{ownerpassword}
\setinterfaceconstant{ownnumber}{eigenenummer}
\setinterfaceconstant{page}{seite}
\setinterfaceconstant{pageboundaries}{seitenbegrenzung}
@@ -1240,6 +1243,7 @@
\setinterfaceconstant{textstyle}{textstil}
\setinterfaceconstant{textwidth}{textbreite}
\setinterfaceconstant{threshold}{threshold}
+\setinterfaceconstant{time}{time}
\setinterfaceconstant{title}{titel}
\setinterfaceconstant{titlecolor}{titelfarbe}
\setinterfaceconstant{titlecommand}{titlecommand}
@@ -1268,12 +1272,14 @@
\setinterfaceconstant{up}{up}
\setinterfaceconstant{urlalternative}{urlalternative}
\setinterfaceconstant{urlspace}{urlspatium}
+\setinterfaceconstant{userpassword}{userpassword}
\setinterfaceconstant{validate}{validieren}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{vbefehl}
\setinterfaceconstant{vcompact}{vcompact}
\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{kopfoffset}
+\setinterfaceconstant{vfactor}{vfaktor}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{viewerprefix}{viewerprefix}
\setinterfaceconstant{voffset}{voffset}
diff --git a/tex/context/base/mkii/mult-en.mkii b/tex/context/base/mkii/mult-en.mkii
index 5c233a0c4..faf268576 100644
--- a/tex/context/base/mkii/mult-en.mkii
+++ b/tex/context/base/mkii/mult-en.mkii
@@ -137,6 +137,7 @@
\setinterfacevariable{chemicals}{chemicals}
\setinterfacevariable{chemistry}{chemistry}
\setinterfacevariable{cite}{cite}
+\setinterfacevariable{closed}{closed}
\setinterfacevariable{color}{color}
\setinterfacevariable{column}{column}
\setinterfacevariable{columns}{columns}
@@ -418,7 +419,7 @@
\setinterfacevariable{positive}{positive}
\setinterfacevariable{postponing}{postponing}
\setinterfacevariable{postscript}{postscript}
-\setinterfacevariable{precedingpage}{followingpage}
+\setinterfacevariable{precedingpage}{precedingpage}
\setinterfacevariable{preference}{preference}
\setinterfacevariable{preview}{preview}
\setinterfacevariable{previous}{previous}
@@ -1027,6 +1028,7 @@
\setinterfaceconstant{otherstext}{otherstext}
\setinterfaceconstant{outermargin}{outermargin}
\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownerpassword}{ownerpassword}
\setinterfaceconstant{ownnumber}{ownnumber}
\setinterfaceconstant{page}{page}
\setinterfaceconstant{pageboundaries}{pageboundaries}
@@ -1240,6 +1242,7 @@
\setinterfaceconstant{textstyle}{textstyle}
\setinterfaceconstant{textwidth}{textwidth}
\setinterfaceconstant{threshold}{threshold}
+\setinterfaceconstant{time}{time}
\setinterfaceconstant{title}{title}
\setinterfaceconstant{titlecolor}{titlecolor}
\setinterfaceconstant{titlecommand}{titlecommand}
@@ -1268,12 +1271,14 @@
\setinterfaceconstant{up}{up}
\setinterfaceconstant{urlalternative}{urlalternative}
\setinterfaceconstant{urlspace}{urlspace}
+\setinterfaceconstant{userpassword}{userpassword}
\setinterfaceconstant{validate}{validate}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{vcommand}
\setinterfaceconstant{vcompact}{vcompact}
\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{veroffset}
+\setinterfaceconstant{vfactor}{vfactor}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{viewerprefix}{viewerprefix}
\setinterfaceconstant{voffset}{voffset}
diff --git a/tex/context/base/mkii/mult-fr.mkii b/tex/context/base/mkii/mult-fr.mkii
index 7cf1bc684..fe883d50f 100644
--- a/tex/context/base/mkii/mult-fr.mkii
+++ b/tex/context/base/mkii/mult-fr.mkii
@@ -137,6 +137,7 @@
\setinterfacevariable{chemicals}{chemicals}
\setinterfacevariable{chemistry}{chemistry}
\setinterfacevariable{cite}{cite}
+\setinterfacevariable{closed}{closed}
\setinterfacevariable{color}{couleur}
\setinterfacevariable{column}{colonne}
\setinterfacevariable{columns}{colonnes}
@@ -418,7 +419,7 @@
\setinterfacevariable{positive}{positif}
\setinterfacevariable{postponing}{postponing}
\setinterfacevariable{postscript}{postscript}
-\setinterfacevariable{precedingpage}{followingpage}
+\setinterfacevariable{precedingpage}{precedingpage}
\setinterfacevariable{preference}{preference}
\setinterfacevariable{preview}{previsualisation}
\setinterfacevariable{previous}{precedent}
@@ -1027,6 +1028,7 @@
\setinterfaceconstant{otherstext}{otherstext}
\setinterfaceconstant{outermargin}{margeexterieure}
\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownerpassword}{ownerpassword}
\setinterfaceconstant{ownnumber}{numeroproprio}
\setinterfaceconstant{page}{page}
\setinterfaceconstant{pageboundaries}{limitespage}
@@ -1240,6 +1242,7 @@
\setinterfaceconstant{textstyle}{styletexte}
\setinterfaceconstant{textwidth}{largeurtexte}
\setinterfaceconstant{threshold}{threshold}
+\setinterfaceconstant{time}{time}
\setinterfaceconstant{title}{titre}
\setinterfaceconstant{titlecolor}{couleurtitre}
\setinterfaceconstant{titlecommand}{titlecommand}
@@ -1268,12 +1271,14 @@
\setinterfaceconstant{up}{up}
\setinterfaceconstant{urlalternative}{alternativeurl}
\setinterfaceconstant{urlspace}{espaceurl}
+\setinterfaceconstant{userpassword}{userpassword}
\setinterfaceconstant{validate}{valider}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{vcommande}
\setinterfaceconstant{vcompact}{vcompact}
\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{veroffset}
+\setinterfaceconstant{vfactor}{vfactor}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{viewerprefix}{viewerprefix}
\setinterfaceconstant{voffset}{voffset}
diff --git a/tex/context/base/mkii/mult-it.mkii b/tex/context/base/mkii/mult-it.mkii
index 38fb2de40..d83672d38 100644
--- a/tex/context/base/mkii/mult-it.mkii
+++ b/tex/context/base/mkii/mult-it.mkii
@@ -137,6 +137,7 @@
\setinterfacevariable{chemicals}{chemicals}
\setinterfacevariable{chemistry}{chemistry}
\setinterfacevariable{cite}{cite}
+\setinterfacevariable{closed}{closed}
\setinterfacevariable{color}{colore}
\setinterfacevariable{column}{colonna}
\setinterfacevariable{columns}{colonne}
@@ -418,7 +419,7 @@
\setinterfacevariable{positive}{positivo}
\setinterfacevariable{postponing}{posporre}
\setinterfacevariable{postscript}{postscript}
-\setinterfacevariable{precedingpage}{followingpage}
+\setinterfacevariable{precedingpage}{precedingpage}
\setinterfacevariable{preference}{preferenza}
\setinterfacevariable{preview}{anteprima}
\setinterfacevariable{previous}{precedente}
@@ -586,6 +587,7 @@
\setinterfacevariable{understrike}{understrike}
\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unframed}{unframed}
+\setinterfacevariable{unicode}{unicode}
\setinterfacevariable{unit}{unita}
\setinterfacevariable{units}{unita}
\setinterfacevariable{unknown}{ignoto}
@@ -1027,6 +1029,7 @@
\setinterfaceconstant{otherstext}{otherstext}
\setinterfaceconstant{outermargin}{margineesterno}
\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownerpassword}{ownerpassword}
\setinterfaceconstant{ownnumber}{numeroproprio}
\setinterfaceconstant{page}{pagina}
\setinterfaceconstant{pageboundaries}{limitipagina}
@@ -1240,6 +1243,7 @@
\setinterfaceconstant{textstyle}{stiletesto}
\setinterfaceconstant{textwidth}{ampiezzatesto}
\setinterfaceconstant{threshold}{threshold}
+\setinterfaceconstant{time}{time}
\setinterfaceconstant{title}{titolo}
\setinterfaceconstant{titlecolor}{coloretitolo}
\setinterfaceconstant{titlecommand}{titlecommand}
@@ -1268,12 +1272,14 @@
\setinterfaceconstant{up}{up}
\setinterfaceconstant{urlalternative}{alternativaurl}
\setinterfaceconstant{urlspace}{spaziourl}
+\setinterfaceconstant{userpassword}{userpassword}
\setinterfaceconstant{validate}{verifica}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{vcomando}
\setinterfaceconstant{vcompact}{vcompact}
\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{veroffset}
+\setinterfaceconstant{vfactor}{vfactor}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{viewerprefix}{viewerprefix}
\setinterfaceconstant{voffset}{voffset}
diff --git a/tex/context/base/mkii/mult-nl.mkii b/tex/context/base/mkii/mult-nl.mkii
index ba7c5a42c..884503363 100644
--- a/tex/context/base/mkii/mult-nl.mkii
+++ b/tex/context/base/mkii/mult-nl.mkii
@@ -137,6 +137,7 @@
\setinterfacevariable{chemicals}{chemicals}
\setinterfacevariable{chemistry}{chemie}
\setinterfacevariable{cite}{cite}
+\setinterfacevariable{closed}{gesloten}
\setinterfacevariable{color}{kleur}
\setinterfacevariable{column}{kolom}
\setinterfacevariable{columns}{kolommen}
@@ -185,6 +186,7 @@
\setinterfacevariable{extremestretch}{extremestretch}
\setinterfacevariable{fact}{gegeven}
\setinterfacevariable{february}{februari}
+\setinterfacevariable{field}{veld}
\setinterfacevariable{figure}{figuur}
\setinterfacevariable{figures}{figuren}
\setinterfacevariable{file}{file}
@@ -794,7 +796,7 @@
\setinterfaceconstant{family}{soort}
\setinterfaceconstant{features}{features}
\setinterfaceconstant{fences}{fences}
-\setinterfaceconstant{field}{field}
+\setinterfaceconstant{field}{veld}
\setinterfaceconstant{fieldbackgroundcolor}{veldachtergrondkleur}
\setinterfaceconstant{fieldframecolor}{veldkaderkleur}
\setinterfaceconstant{fieldlayer}{veldlaag}
@@ -849,6 +851,7 @@
\setinterfaceconstant{headerstate}{hoofdstatus}
\setinterfaceconstant{headlabel}{koplabel}
\setinterfaceconstant{headnumber}{kopnummer}
+\setinterfaceconstant{headseparator}{kopscheider}
\setinterfaceconstant{headstyle}{kopletter}
\setinterfaceconstant{height}{hoogte}
\setinterfaceconstant{hfactor}{hfactor}
@@ -1025,6 +1028,7 @@
\setinterfaceconstant{otherstext}{otherstext}
\setinterfaceconstant{outermargin}{buitenmarge}
\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownerpassword}{ownerpassword}
\setinterfaceconstant{ownnumber}{eigennummer}
\setinterfaceconstant{page}{pagina}
\setinterfaceconstant{pageboundaries}{paginaovergangen}
@@ -1075,6 +1079,7 @@
\setinterfaceconstant{preview}{preview}
\setinterfaceconstant{previous}{vorige}
\setinterfaceconstant{previousnumber}{vorigenummer}
+\setinterfaceconstant{print}{print}
\setinterfaceconstant{printable}{printbaar}
\setinterfaceconstant{process}{proces}
\setinterfaceconstant{profile}{profile}
@@ -1160,8 +1165,10 @@
\setinterfaceconstant{sidemethod}{zijmethode}
\setinterfaceconstant{sidespaceafter}{zijnawit}
\setinterfaceconstant{sidespacebefore}{zijvoorwit}
+\setinterfaceconstant{sidespaceinbetween}{zijtussenwit}
\setinterfaceconstant{sidethreshold}{sidethreshold}
\setinterfaceconstant{sign}{teken}
+\setinterfaceconstant{simplecommand}{simpelcommando}
\setinterfaceconstant{size}{formaat}
\setinterfaceconstant{slantedfeatures}{slantedfeatures}
\setinterfaceconstant{slantedfont}{slantedfont}
@@ -1235,6 +1242,7 @@
\setinterfaceconstant{textstyle}{tekstletter}
\setinterfaceconstant{textwidth}{tekstbreedte}
\setinterfaceconstant{threshold}{threshold}
+\setinterfaceconstant{time}{tijd}
\setinterfaceconstant{title}{titel}
\setinterfaceconstant{titlecolor}{titelkleur}
\setinterfaceconstant{titlecommand}{titelcommando}
@@ -1263,12 +1271,14 @@
\setinterfaceconstant{up}{up}
\setinterfaceconstant{urlalternative}{urlvariant}
\setinterfaceconstant{urlspace}{urlspatie}
+\setinterfaceconstant{userpassword}{userpassword}
\setinterfaceconstant{validate}{valideer}
\setinterfaceconstant{values}{waarden}
\setinterfaceconstant{vcommand}{vcommando}
\setinterfaceconstant{vcompact}{vcomprimeer}
\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{kopoffset}
+\setinterfaceconstant{vfactor}{vfactor}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{viewerprefix}{viewerprefix}
\setinterfaceconstant{voffset}{voffset}
diff --git a/tex/context/base/mkii/mult-pe.mkii b/tex/context/base/mkii/mult-pe.mkii
index 534c239da..57cbe5600 100644
--- a/tex/context/base/mkii/mult-pe.mkii
+++ b/tex/context/base/mkii/mult-pe.mkii
@@ -137,6 +137,7 @@
\setinterfacevariable{chemicals}{chemicals}
\setinterfacevariable{chemistry}{chemistry}
\setinterfacevariable{cite}{cite}
+\setinterfacevariable{closed}{closed}
\setinterfacevariable{color}{رنگ}
\setinterfacevariable{column}{ستون}
\setinterfacevariable{columns}{ستونها}
@@ -418,7 +419,7 @@
\setinterfacevariable{positive}{مثبت}
\setinterfacevariable{postponing}{تاخیر}
\setinterfacevariable{postscript}{پست‌اسکریپت}
-\setinterfacevariable{precedingpage}{followingpage}
+\setinterfacevariable{precedingpage}{precedingpage}
\setinterfacevariable{preference}{ترجیح}
\setinterfacevariable{preview}{پیش‌دید}
\setinterfacevariable{previous}{قبلی}
@@ -1027,6 +1028,7 @@
\setinterfaceconstant{otherstext}{otherstext}
\setinterfaceconstant{outermargin}{حاشیه‌خارجی}
\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownerpassword}{ownerpassword}
\setinterfaceconstant{ownnumber}{شماره‌خود}
\setinterfaceconstant{page}{صفحه}
\setinterfaceconstant{pageboundaries}{مرزهای‌صفحه}
@@ -1240,6 +1242,7 @@
\setinterfaceconstant{textstyle}{سبک‌متن}
\setinterfaceconstant{textwidth}{عرض‌متن}
\setinterfaceconstant{threshold}{threshold}
+\setinterfaceconstant{time}{time}
\setinterfaceconstant{title}{عنوان}
\setinterfaceconstant{titlecolor}{رنگ‌عنوان}
\setinterfaceconstant{titlecommand}{فرمان‌عنوان}
@@ -1268,12 +1271,14 @@
\setinterfaceconstant{up}{up}
\setinterfaceconstant{urlalternative}{urlalternative}
\setinterfaceconstant{urlspace}{urlspace}
+\setinterfaceconstant{userpassword}{userpassword}
\setinterfaceconstant{validate}{تاییداعتبار}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{vcommand}
\setinterfaceconstant{vcompact}{vcompact}
\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{آفست‌عم}
+\setinterfaceconstant{vfactor}{vfactor}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{viewerprefix}{viewerprefix}
\setinterfaceconstant{voffset}{آفست‌ع}
diff --git a/tex/context/base/mkii/mult-ro.mkii b/tex/context/base/mkii/mult-ro.mkii
index 46b61c882..786319956 100644
--- a/tex/context/base/mkii/mult-ro.mkii
+++ b/tex/context/base/mkii/mult-ro.mkii
@@ -137,6 +137,7 @@
\setinterfacevariable{chemicals}{chemicals}
\setinterfacevariable{chemistry}{chemistry}
\setinterfacevariable{cite}{cite}
+\setinterfacevariable{closed}{closed}
\setinterfacevariable{color}{culoare}
\setinterfacevariable{column}{coloana}
\setinterfacevariable{columns}{coloane}
@@ -418,7 +419,7 @@
\setinterfacevariable{positive}{positiv}
\setinterfacevariable{postponing}{postponing}
\setinterfacevariable{postscript}{postscript}
-\setinterfacevariable{precedingpage}{followingpage}
+\setinterfacevariable{precedingpage}{precedingpage}
\setinterfacevariable{preference}{preferinta}
\setinterfacevariable{preview}{previzualizare}
\setinterfacevariable{previous}{precedent}
@@ -586,6 +587,7 @@
\setinterfacevariable{understrike}{understrike}
\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unframed}{unframed}
+\setinterfacevariable{unicode}{unicode}
\setinterfacevariable{unit}{unitate}
\setinterfacevariable{units}{unitati}
\setinterfacevariable{unknown}{necunoscut}
@@ -1027,6 +1029,7 @@
\setinterfaceconstant{otherstext}{otherstext}
\setinterfaceconstant{outermargin}{outermargin}
\setinterfaceconstant{overprint}{overprint}
+\setinterfaceconstant{ownerpassword}{ownerpassword}
\setinterfaceconstant{ownnumber}{numarpropriu}
\setinterfaceconstant{page}{pagina}
\setinterfaceconstant{pageboundaries}{marginipagina}
@@ -1240,6 +1243,7 @@
\setinterfaceconstant{textstyle}{stiltext}
\setinterfaceconstant{textwidth}{latimetext}
\setinterfaceconstant{threshold}{threshold}
+\setinterfaceconstant{time}{time}
\setinterfaceconstant{title}{titlu}
\setinterfaceconstant{titlecolor}{culoaretitlu}
\setinterfaceconstant{titlecommand}{titlecommand}
@@ -1268,12 +1272,14 @@
\setinterfaceconstant{up}{up}
\setinterfaceconstant{urlalternative}{urlalternativ}
\setinterfaceconstant{urlspace}{spatiuurl}
+\setinterfaceconstant{userpassword}{userpassword}
\setinterfaceconstant{validate}{verifica}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{comandav}
\setinterfaceconstant{vcompact}{vcompact}
\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{veroffset}
+\setinterfaceconstant{vfactor}{vfactor}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{viewerprefix}{viewerprefix}
\setinterfaceconstant{voffset}{voffset}
diff --git a/tex/context/base/mkii/strc-reg.mkii b/tex/context/base/mkii/strc-reg.mkii
index 45be82525..a8d05fb78 100644
--- a/tex/context/base/mkii/strc-reg.mkii
+++ b/tex/context/base/mkii/strc-reg.mkii
@@ -18,7 +18,7 @@
% new: eigennummer=ja => eerste {} ipv pag nummer
\unprotect
-
+
%D Isolated but still indocumented.
% Formaat tex-utility-input-file <jobname.tui>:
@@ -1176,7 +1176,7 @@
\def\defineregister
{\dodoubleargument\dodefineregister}
-
+
\def\registerlengte{\utilityregisterlength}
\def\utilityregisterlength{0}
diff --git a/tex/context/base/mkii/unic-003.mkii b/tex/context/base/mkii/unic-003.mkii
index ad7d6df6a..91512ea54 100644
--- a/tex/context/base/mkii/unic-003.mkii
+++ b/tex/context/base/mkii/unic-003.mkii
@@ -100,9 +100,9 @@
\strippedcsname \greekupsilondialytika \or
\strippedcsname \greekomicrontonos \or
\strippedcsname \greekupsilontonos \or
- \strippedcsname \greekomegatonos \or % was greeek!
+ \strippedcsname \greekomegatonos \or
\strippedcsname \unknownchar \or
- \strippedcsname \unknownchar \or % beta alt
+ \strippedcsname \greekbetaalt \or
\strippedcsname \greekthetaalt \or
\strippedcsname \unknownchar \or % upsilon hook
\strippedcsname \unknownchar \or
diff --git a/tex/context/base/mkii/xetx-chr.mkii b/tex/context/base/mkii/xetx-chr.mkii
index ca9c4aaa4..66ae0d636 100644
--- a/tex/context/base/mkii/xetx-chr.mkii
+++ b/tex/context/base/mkii/xetx-chr.mkii
@@ -462,6 +462,7 @@
\def\greekomicrontonos {\char"003CC } % GREEK SMALL LETTER OMICRON WITH TONOS: ό
\def\greekupsilontonos {\char"003CD } % GREEK SMALL LETTER UPSILON WITH TONOS: ύ
\def\greekomegatonos {\char"003CE } % GREEK SMALL LETTER OMEGA WITH TONOS: ώ
+\def\greekbetaalt {\char"003D0 } % GREEK BETA SYMBOL: ϐ
\def\greekthetaalt {\char"003D1 } % GREEK THETA SYMBOL: ϑ
\def\greekphialt {\char"003D5 } % GREEK PHI SYMBOL: ϕ
\def\greekpialt {\char"003D6 } % GREEK PI SYMBOL: ϖ
diff --git a/tex/context/base/mkiv/anch-bck.mkvi b/tex/context/base/mkiv/anch-bck.mkvi
index 348ea0ad1..96dd0cdf5 100644
--- a/tex/context/base/mkiv/anch-bck.mkvi
+++ b/tex/context/base/mkiv/anch-bck.mkvi
@@ -47,7 +47,7 @@
\unexpanded\def\anch_backgrounds_text_initialize
{\doifelsepositionsused\enableparpositions\donothing
- \global\let\anch_backgrounds_text_initialize\relax}
+ \glet\anch_backgrounds_text_initialize\relax}
\appendtoks
\anch_backgrounds_text_initialize
@@ -352,7 +352,7 @@
{\ifproductionrun
\enabletextarearegistration
\enablehiddenbackground
- \global\let\checkpositionoverlays\relax
+ \glet\checkpositionoverlays\relax
\fi}
% shape handling
@@ -453,55 +453,55 @@
\strc_floats_mark_as_free
\plustwo
\zeropoint
- \d_page_sides_leftskip
+ \d_page_sides_rightoffset
\d_page_sides_topskip
\d_page_sides_bottomskip
\or % leftedge
\strc_floats_mark_as_free
\plustwo
\zeropoint
- \d_page_sides_leftskip
+ \d_page_sides_rightoffset
\d_page_sides_topskip
\d_page_sides_bottomskip
\or % leftmargin
\strc_floats_mark_as_free
\plustwo
\zeropoint
- \d_page_sides_leftskip
+ \d_page_sides_rightoffset
\d_page_sides_topskip
\d_page_sides_bottomskip
\or % leftside
\strc_floats_mark_as_free
\plustwo
- \d_page_sides_leftskip
- \d_strc_floats_margin
+ \d_page_sides_leftskip % maybe too
+ \d_page_sides_margin
\d_page_sides_topskip
\d_page_sides_bottomskip
\or % rightside
\strc_floats_mark_as_free
\plusthree
- \d_strc_floats_margin
- \d_page_sides_rightskip
+ \d_page_sides_margin
+ \d_page_sides_rightskip % maybe too
\d_page_sides_topskip
\d_page_sides_bottomskip
\or % rightmargin
\strc_floats_mark_as_free
\plusthree
- \d_page_sides_rightskip
+ \d_page_sides_leftoffset
\zeropoint
\d_page_sides_topskip
\d_page_sides_bottomskip
\or % rightedge
\strc_floats_mark_as_free
\plusthree
- \d_page_sides_rightskip
+ \d_page_sides_leftoffset
\zeropoint
\d_page_sides_topskip
\d_page_sides_bottomskip
\or % cutspace
\strc_floats_mark_as_free
\plusthree
- \d_page_sides_rightskip
+ \d_page_sides_leftoffset
\zeropoint
\d_page_sides_topskip
\d_page_sides_bottomskip
diff --git a/tex/context/base/mkiv/anch-pgr.lua b/tex/context/base/mkiv/anch-pgr.lua
index ca5a5a8af..14afa3967 100644
--- a/tex/context/base/mkiv/anch-pgr.lua
+++ b/tex/context/base/mkiv/anch-pgr.lua
@@ -56,13 +56,10 @@ graphics.backgrounds = backgrounds
-- -- --
local texsetattribute = tex.setattribute
-local pdfgetpos = pdf.getpos -- why not a generic name !
local a_textbackground = attributes.private("textbackground")
local nuts = nodes.nuts
-local tonut = nodes.tonut
-local tonode = nodes.tonode
local new_latelua = nuts.pool.latelua
local new_rule = nuts.pool.rule
@@ -82,11 +79,12 @@ local localpar_code = nodecodes.localpar
local insert_before = nuts.insert_before
local insert_after = nuts.insert_after
-local processranges = nodes.processranges
+local processranges = nuts.processranges
local unsetvalue = attributes.unsetvalue
local jobpositions = job.positions
+local getpos = jobpositions.getpos
local data = { }
local realpage = 1
@@ -96,10 +94,17 @@ local enabled = false
-- Freeing the data is somewhat tricky as we can have backgrounds spanning
-- many pages but for an arbitrary background shape that is not so common.
-local function check(a,index,depth,d,where,ht,dp)
+local function check(specification)
+ local a = specification.attribute
+ local index = specification.index
+ local depth = specification.depth
+ local d = specification.data
+ local where = specification.where
+ local ht = specification.ht
+ local dp = specification.dp
-- this is not yet r2l ready
local w = d.shapes[realpage]
- local x, y = pdfgetpos()
+ local x, y = getpos()
if trace_ranges then
report_shapes("attribute %i, index %i, depth %i, location %s, position (%p,%p)",
a,index,depth,where,x,y)
@@ -109,7 +114,7 @@ local function check(a,index,depth,d,where,ht,dp)
n = n + 1
d.index = index
d.depth = depth
--- w[n] = { x, x, y, ht, dp }
+ -- w[n] = { x, x, y, ht, dp }
w[n] = { y, ht, dp, x, x }
else
local wn = w[n]
@@ -150,13 +155,13 @@ local function flush(head,f,l,a,parent,depth)
local ix = index
local ht = getheight(parent)
local dp = getdepth(parent)
- local ln = new_latelua(function() check(a,ix,depth,d,"l",ht,dp) end)
- local rn = new_latelua(function() check(a,ix,depth,d,"r",ht,dp) end)
+ local ln = new_latelua { action = check, attribute = a, index = ix, depth = depth, data = d, where = "l", ht = ht, dp = dp }
+ local rn = new_latelua { action = check, attribute = a, index = ix, depth = depth, data = d, where = "r", ht = ht, dp = dp }
if trace_ranges then
ln = new_hlist(setlink(new_rule(65536,65536*4,0),new_kern(-65536),ln))
rn = new_hlist(setlink(new_rule(65536,0,65536*4),new_kern(-65536),rn))
end
- if getid(f) == localpar_code then -- we need to clean this mess
+ if getid(f) == localpar_code and getsubtype(f) == 0 then -- we need to clean this mess
insert_after(head,f,ln)
else
head, f = insert_before(head,f,ln)
@@ -213,10 +218,8 @@ end
nodes.handlers.textbackgrounds = function(head,where,parent) -- we have hlistdir and local dir
-- todo enable action in register
- head = tonut(head)
index = index + 1
- local head, done = processranges(a_textbackground,flush,head,parent)
- return tonode(head), done
+ return processranges(a_textbackground,flush,head,parent)
end
interfaces.implement {
@@ -228,6 +231,8 @@ interfaces.implement {
-- optimized already but we can assume a cycle i.e. prune the last point and then
-- even less code .. we could merge some loops but his is more robust
+-- use idiv here
+
local function topairs(t,n)
local r = { }
for i=1,n do
@@ -237,7 +242,7 @@ local function topairs(t,n)
return concat(r," ")
end
-local eps = 65536 / 4 -- 2
+local eps = 65536 / 4
local pps = eps
local nps = - pps
@@ -509,7 +514,8 @@ local function shape(kind,b,p,realpage,xmin,xmax,ymin,ymax,fh,ld)
-- use height of b and depth of e, maybe check for weird border
-- cases here
if fh then
- local lsf, rsf = ls[1], rs[1]
+ local lsf = ls[1]
+ local rsf = rs[1]
if lsf[2] < fh then
lsf[2] = fh
end
@@ -518,7 +524,8 @@ local function shape(kind,b,p,realpage,xmin,xmax,ymin,ymax,fh,ld)
end
end
if fd then
- local lsl, rsl = ls[n], rs[n]
+ local lsl = ls[n]
+ local rsl = rs[n]
if lsl[2] > fd then
lsl[2] = fd
end
@@ -535,12 +542,18 @@ local function shape(kind,b,p,realpage,xmin,xmax,ymin,ymax,fh,ld)
end
local function singlepart(b,e,p,realpage,r,left,right)
- local bx, by = b.x, b.y
- local ex, ey = e.x, e.y
- local rx, ry = r.x, r.y
- local bh, bd = by + b.h, by - b.d
- local eh, ed = ey + e.h, ey - e.d
- local rh, rd = ry + r.h, ry - r.d
+ local bx = b.x
+ local by = b.y
+ local ex = e.x
+ local ey = e.y
+ local rx = r.x
+ local ry = r.y
+ local bh = by + b.h
+ local bd = by - b.d
+ local eh = ey + e.h
+ local ed = ey - e.d
+ local rh = ry + r.h
+ local rd = ry - r.d
local rw = rx + r.w
if left then
rx = rx + left
@@ -593,10 +606,14 @@ local function singlepart(b,e,p,realpage,r,left,right)
end
local function firstpart(b,e,p,realpage,r,left,right)
- local bx, by = b.x, b.y
- local rx, ry = r.x, r.y
- local bh, bd = by + b.h, by - b.d
- local rh, rd = ry + r.h, ry - r.d
+ local bx = b.x
+ local by = b.y
+ local rx = r.x
+ local ry = r.y
+ local bh = by + b.h
+ local bd = by - b.d
+ local rh = ry + r.h
+ local rd = ry - r.d
local rw = rx + r.w
if left then
rx = rx + left
@@ -630,8 +647,10 @@ local function firstpart(b,e,p,realpage,r,left,right)
end
local function middlepart(b,e,p,realpage,r,left,right)
- local rx, ry = r.x, r.y
- local rh, rd = ry + r.h, ry - r.d
+ local rx = r.x
+ local ry = r.y
+ local rh = ry + r.h
+ local rd = ry - r.d
local rw = rx + r.w
if left then
rx = rx + left
@@ -654,10 +673,14 @@ local function middlepart(b,e,p,realpage,r,left,right)
end
local function lastpart(b,e,p,realpage,r,left,right)
- local ex, ey = e.x, e.y
- local rx, ry = r.x, r.y
- local eh, ed = ey + e.h, ey - e.d
- local rh, rd = ry + r.h, ry - r.d
+ local ex = e.x
+ local ey = e.y
+ local rx = r.x
+ local ry = r.y
+ local eh = ey + e.h
+ local ed = ey - e.d
+ local rh = ry + r.h
+ local rd = ry - r.d
local rw = rx + r.w
if left then
rx = rx + left
@@ -740,7 +763,7 @@ local function calculatemultipar(tag)
local bp = b.p -- page
if trace_shapes then
report_shapes("tag %a, left %p, right %p, par %s, page %s, column %s",
- left,right,bn or "-",bp or "-",bc or "-")
+ tag,left,right,bn or "-",bp or "-",bc or "-")
end
--
if bindex == eindex then
@@ -844,8 +867,10 @@ local function freemultipar(pagedata,frees) -- ,k
local areas = { }
data.areas = areas
- local f_1, n_1 = { }, 0
- local f_2, n_2 = { }, 0
+ local f_1 = { }
+ local n_1 = 0
+ local f_2 = { }
+ local n_2 = 0
for i=1,#frees do
local f = frees[i]
local k = f.k
@@ -908,14 +933,18 @@ local function freemultipar(pagedata,frees) -- ,k
-- we can collect the coordinates first
local function check_two(area,frees)
- local ul = area[1]
- local ur = area[2]
- local lr = area[3]
- local ll = area[4]
- local ulx, uly = ul[1], ul[2]
- local urx, ury = ur[1], ur[2]
- local lrx, lry = lr[1], lr[2]
- local llx, lly = ll[1], ll[2]
+ local ul = area[1]
+ local ur = area[2]
+ local lr = area[3]
+ local ll = area[4]
+ local ulx = ul[1]
+ local uly = ul[2]
+ local urx = ur[1]
+ local ury = ur[2]
+ local lrx = lr[1]
+ local lry = lr[2]
+ local llx = ll[1]
+ local lly = ll[2]
local temp = { }
local n = 0
@@ -1108,12 +1137,16 @@ local function fetchmultipar(n,anchor,page)
report_graphics("fetching %a at page %s using anchor %a containing %s multipars",
n,page,anchor,nofmultipars)
end
- local x, y = a.x, a.y
- local w, h, d = a.w, a.h, a.d
- local bpos = data.bpos
- local bh, bd = bpos.h, bpos.d
- local result = { false } -- slot 1 will be set later
- local n = 0
+ local x = a.x
+ local y = a.y
+ local w = a.w
+ local h = a.h
+ local d = a.d
+ local bpos = data.bpos
+ local bh = bpos.h
+ local bd = bpos.d
+ local result = { false } -- slot 1 will be set later
+ local n = 0
for i=1,nofmultipars do
local data = pagedata[i]
local location = data.location
@@ -1178,7 +1211,8 @@ implement {
if type(tags) == "string" then
tags = utilities.parsers.settings_to_array(tags)
end
- local list, nofboxes = { }, 0
+ local list = { }
+ local nofboxes = 0
for i=1,#tags do
local tag= tags[i]
local c = collected[tag]
@@ -1187,7 +1221,11 @@ implement {
if r then
r = collected[r]
if r then
- local rx, ry, rw, rh, rd = r.x, r.y, r.w, r.h, r.d
+ local rx = r.x
+ local ry = r.y
+ local rw = r.w
+ local rh = r.h
+ local rd = r.d
local cx = c.x - rx
local cy = c.y
local cw = cx + c.w
diff --git a/tex/context/base/mkiv/anch-pgr.mkiv b/tex/context/base/mkiv/anch-pgr.mkiv
index e49d18b8f..7fa378cd1 100644
--- a/tex/context/base/mkiv/anch-pgr.mkiv
+++ b/tex/context/base/mkiv/anch-pgr.mkiv
@@ -66,7 +66,7 @@
\def\anch_positions_action_indeed_yes % we need a way to figure out if we have actions
{\begingroup
- \setbox\scratchbox\hbox
+ \setbox\scratchbox\hbox % \hpack
{\anch_positions_trace_action_yes
\the\everyinsertpositionaction
\the\everypositionaction
@@ -130,12 +130,12 @@
\else
\c_anch_page_width \paperwidth
\c_anch_page_height\paperheight
- \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hbox{\box#1}\fi
+ \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hpack{\box#1}\fi
\fi
\else
\c_anch_page_width \paperwidth
\c_anch_page_height\paperheight
- \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hbox{\box#1}\fi
+ \anch_make_page_box{#1}% \ifvbox#1\setbox#1\hpack{\box#1}\fi
\fi
\fi\fi}
@@ -157,7 +157,7 @@
\endgroup}
\def\anch_positions_place_anchors_nop
- {\vskip\textheight}
+ {\vkern\textheight}
%D \macros
%D {positionoverlay,startpositionoverlay}
@@ -243,7 +243,7 @@
\let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used
\the\everyinsertpositionaction
\copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid
- \setbox\scratchbox\hbox to \d_overlay_width
+ \setbox\scratchbox\hbox to \d_overlay_width % \hpack
{\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
\ht\scratchbox\d_overlay_height
\dp\scratchbox\zeropoint
@@ -275,7 +275,7 @@
\let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used
\the\everyinsertpositionaction
\copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid
- \setbox\scratchbox\hbox to \d_overlay_width
+ \setbox\scratchbox\hbox to \d_overlay_width % \hpack
{\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
\ht\scratchbox\d_overlay_height
\dp\scratchbox\zeropoint
@@ -366,7 +366,7 @@
\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\b_anch_positions_graphic\hbox
+ \setbox\b_anch_positions_graphic\hbox % \hpack
{\ignorespaces\csname#1#2\endcsname\removelastspace}%
\smashbox\b_anch_positions_graphic
\box\b_anch_positions_graphic
diff --git a/tex/context/base/mkiv/anch-pos.lua b/tex/context/base/mkiv/anch-pos.lua
index e5f58c36c..ade992792 100644
--- a/tex/context/base/mkiv/anch-pos.lua
+++ b/tex/context/base/mkiv/anch-pos.lua
@@ -20,8 +20,12 @@ more efficient.</p>
-- this is one of the first modules using scanners and we need to replace
-- it by implement and friends
+-- we could have namespaces, like p, page, region, columnarea, textarea but then
+-- we need virtual table accessors as well as have tag/id accessors ... we don't
+-- save much here (at least not now)
+
local tostring, next, rawget, rawset, setmetatable, tonumber = tostring, next, rawget, rawset, setmetatable, tonumber
-local sort, sortedhash, sortedkeys = table.sort, table.sortedhash, table.sortedkeys
+local sort = table.sort
local format, gmatch = string.format, string.gmatch
local rawget = rawget
local lpegmatch = lpeg.match
@@ -40,7 +44,8 @@ local scanners = interfaces.scanners
local commands = commands
local context = context
-local ctxnode = context.nodes.flush
+
+local ctx_latelua = context.latelua
local tex = tex
local texgetcount = tex.getcount
@@ -63,12 +68,12 @@ local getbox = nuts.getbox
local getid = nuts.getid
local getwhd = nuts.getwhd
------ hlist_code = nodes.listcodes.hlist
+local hlist_code = nodes.nodecodes.hlist
local find_tail = nuts.tail
+local hpack = nuts.hpack
local new_latelua = nuts.pool.latelua
-local new_latelua_node = nodes.pool.latelua
local variables = interfaces.variables
local v_text = variables.text
@@ -236,7 +241,6 @@ end
-- t[#t+1] = data
-- end
--
--- --
-- local pages = structures.pages.collected
-- if pages then
-- local last = nil
@@ -326,9 +330,19 @@ local nofpages = nil
-- beware ... we're not sparse here as lua will reserve slots for the nilled
-local getpos = function() getpos = backends.codeinjections.getpos return getpos () end
-local gethpos = function() gethpos = backends.codeinjections.gethpos return gethpos() end
-local getvpos = function() getvpos = backends.codeinjections.getvpos return getvpos() end
+local getpos, gethpos, getvpos
+
+function jobpositions.registerhandlers(t)
+ getpos = t and t.getpos or function() return 0, 0 end
+ gethpos = t and t.gethpos or function() return 0 end
+ getvpos = t and t.getvpos or function() return 0 end
+end
+
+function jobpositions.getpos () return getpos () end
+function jobpositions.gethpos() return gethpos() end
+function jobpositions.getvpos() return getvpos() end
+
+jobpositions.registerhandlers()
local function setall(name,p,x,y,w,h,d,extra)
tobesaved[name] = {
@@ -386,9 +400,28 @@ end
-- analyze some files (with lots if margindata) and then when one key optionally
-- use that one instead of a table (so, a 3rd / 4th argument: key, e.g. "x")
-local function set(name,index,val) -- ,key
- local data = enhance(val or index)
- if val then
+local function set(name,index,value) -- ,key
+ local data = enhance(value or index)
+ if value then
+ container = tobesaved[name]
+ if not container then
+ tobesaved[name] = {
+ [index] = data
+ }
+ else
+ container[index] = data
+ end
+ else
+ tobesaved[name] = data
+ end
+end
+
+local function setspec(specification)
+ local name = specification.name
+ local index = specification.index
+ local value = specification.value
+ local data = enhance(value or index)
+ if value then
container = tobesaved[name]
if not container then
tobesaved[name] = {
@@ -411,16 +444,11 @@ local function get(id,index)
end
end
-------------.setdim = setdim
-jobpositions.setall = setall
-jobpositions.set = set
-jobpositions.get = get
-
--- scanners.setpos = setall
-
--- trackers.enable("tokens.compi*")
-
--- something weird: the compiler fails us here
+------------.setdim = setdim
+jobpositions.setall = setall
+jobpositions.set = set
+jobpositions.setspec = setspec
+jobpositions.get = get
scanners.dosaveposition = compilescanner {
actions = setall, -- name p x y
@@ -442,7 +470,8 @@ scanners.dosavepositionplus = compilescanner {
-- not much gain in keeping stack (inc/dec instead of insert/remove)
-local function b_column(tag)
+local function b_column(specification)
+ local tag = specification.tag
local x = gethpos()
tobesaved[tag] = {
r = true,
@@ -453,7 +482,7 @@ local function b_column(tag)
column = tag
end
-local function e_column(tag)
+local function e_column()
local t = tobesaved[column]
if not t then
-- something's wrong
@@ -479,7 +508,7 @@ scanners.bposcolumnregistered = function() -- tag
local tag = scanstring()
insert(columns,tag)
column = tag
- ctxnode(new_latelua_node(function() b_column(tag) end))
+ ctx_latelua { action = b_column, tag = tag }
end
scanners.eposcolumn = function()
@@ -488,38 +517,42 @@ scanners.eposcolumn = function()
end
scanners.eposcolumnregistered = function()
- ctxnode(new_latelua_node(e_column))
+ ctx_latelua { action = e_column }
remove(columns)
column = columns[#columns]
end
-- regions
-local function b_region(tag)
+local function b_region(specification)
+ local tag = specification.tag or specification
local last = tobesaved[tag]
local x, y = getpos()
last.x = x ~= 0 and x or nil
last.y = y ~= 0 and y or nil
last.p = texgetcount("realpageno")
- insert(regions,tag)
+ insert(regions,tag) -- todo: fast stack
region = tag
end
-local function e_region(correct)
+local function e_region(specification)
local last = tobesaved[region]
local y = getvpos()
- if correct then
+ local x, y = getpos()
+ if specification.correct then
local h = (last.y or 0) - y
last.h = h ~= 0 and h or nil
end
last.y = y ~= 0 and y or nil
- remove(regions)
+ remove(regions) -- todo: fast stack
region = regions[#regions]
end
jobpositions.b_region = b_region
jobpositions.e_region = e_region
+local lastregion
+
local function setregionbox(n,tag,k,lo,ro,to,bo) -- kind
if not tag or tag == "" then
nofregions = nofregions + 1
@@ -527,34 +560,34 @@ local function setregionbox(n,tag,k,lo,ro,to,bo) -- kind
end
local box = getbox(n)
local w, h, d = getwhd(box)
- local x, y = getpos() -- hm, makes no sense here
tobesaved[tag] = {
- -- p = texgetcount("realpageno"), -- we copy them
- x = x ~= 0 and x or nil, -- was true
- y = y ~= 0 and y or nil,
- w = w ~= 0 and w or nil,
- h = h ~= 0 and h or nil,
- d = d ~= 0 and d or nil,
- k = k ~= 0 and k or nil,
+ -- p = texgetcount("realpageno"), -- we copy them
+ x = 0,
+ y = 0,
+ w = w ~= 0 and w or nil,
+ h = h ~= 0 and h or nil,
+ d = d ~= 0 and d or nil,
+ k = k ~= 0 and k or nil,
lo = lo ~= 0 and lo or nil,
ro = ro ~= 0 and ro or nil,
to = to ~= 0 and to or nil,
bo = bo ~= 0 and bo or nil,
}
+ lastregion = tag
return tag, box
end
local function markregionbox(n,tag,correct,...) -- correct needs checking
local tag, box = setregionbox(n,tag,...)
-- todo: check if tostring is needed with formatter
- local push = new_latelua(function() b_region(tag) end)
- local pop = new_latelua(function() e_region(correct) end)
+ local push = new_latelua { action = b_region, tag = tag }
+ local pop = new_latelua { action = e_region, correct = correct }
-- maybe we should construct a hbox first (needs experimenting) so that we can avoid some at the tex end
local head = getlist(box)
- -- no :
+ -- no, this fails with \framed[region=...] .. needs thinking
-- if getid(box) ~= hlist_code then
-- -- report("mark region box assumes a hlist, fix this for %a",tag)
- -- head = nuts.hpack(head)
+ -- head = hpack(head)
-- end
if head then
local tail = find_tail(head)
@@ -584,7 +617,7 @@ end
local nofparagraphs = 0
-scanners.parpos = function() -- todo: relate to localpar (so this is an intermediate variant)
+scanners.parpos = function()
nofparagraphs = nofparagraphs + 1
texsetcount("global","c_anch_positions_paragraph",nofparagraphs)
local box = getbox("strutbox")
@@ -623,14 +656,14 @@ scanners.parpos = function() -- todo: relate to localpar (so this is an intermed
if parshape and #parshape > 0 then
t.ps = parshape
end
- local tag = f_p_tag(nofparagraphs)
- tobesaved[tag] = t
- ctxnode(new_latelua_node(function() enhance(tobesaved[tag]) end))
+ local name = f_p_tag(nofparagraphs)
+ tobesaved[name] = t
+ ctx_latelua { action = enhance, specification = t }
end
scanners.dosetposition = function() -- name
local name = scanstring()
- tobesaved[name] = {
+ local spec = {
p = true,
c = column,
r = true,
@@ -639,15 +672,15 @@ scanners.dosetposition = function() -- name
n = nofparagraphs > 0 and nofparagraphs or nil,
r2l = texgetcount("inlinelefttoright") == 1 or nil,
}
- ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end))
+ ctx_latelua { action = enhance, specification = spec }
end
scanners.dosetpositionwhd = function() -- name w h d extra
local name = scanstring()
- local w = scandimen()
- local h = scandimen()
- local d = scandimen()
- tobesaved[name] = {
+ local w = scandimen()
+ local h = scandimen()
+ local d = scandimen()
+ local spec = {
p = true,
c = column,
r = true,
@@ -659,14 +692,14 @@ scanners.dosetpositionwhd = function() -- name w h d extra
n = nofparagraphs > 0 and nofparagraphs or nil,
r2l = texgetcount("inlinelefttoright") == 1 or nil,
}
- ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end))
+ ctx_latelua { action = enhance, specification = spec }
end
scanners.dosetpositionbox = function() -- name box
local name = scanstring()
local box = getbox(scaninteger())
local w, h, d = getwhd(box)
- tobesaved[name] = {
+ local spec = {
p = true,
c = column,
r = true,
@@ -678,15 +711,15 @@ scanners.dosetpositionbox = function() -- name box
n = nofparagraphs > 0 and nofparagraphs or nil,
r2l = texgetcount("inlinelefttoright") == 1 or nil,
}
- ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end))
+ ctx_latelua { action = enhance, specification = spec }
end
scanners.dosetpositionplus = function() -- name w h d extra
local name = scanstring()
- local w = scandimen()
- local h = scandimen()
- local d = scandimen()
- tobesaved[name] = {
+ local w = scandimen()
+ local h = scandimen()
+ local d = scandimen()
+ local spec = {
p = true,
c = column,
r = true,
@@ -699,14 +732,14 @@ scanners.dosetpositionplus = function() -- name w h d extra
e = scanstring(),
r2l = texgetcount("inlinelefttoright") == 1 or nil,
}
- ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end))
+ ctx_latelua { action = enhance, specification = spec }
end
scanners.dosetpositionstrut = function() -- name
local name = scanstring()
local box = getbox("strutbox")
local w, h, d = getwhd(box)
- tobesaved[name] = {
+ local spec = {
p = true,
c = column,
r = true,
@@ -717,7 +750,7 @@ scanners.dosetpositionstrut = function() -- name
n = nofparagraphs > 0 and nofparagraphs or nil,
r2l = texgetcount("inlinelefttoright") == 1 or nil,
}
- ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end))
+ ctx_latelua { action = enhance, specification = spec }
end
scanners.dosetpositionstrutkind = function() -- name
@@ -725,7 +758,7 @@ scanners.dosetpositionstrutkind = function() -- name
local kind = scaninteger()
local box = getbox("strutbox")
local w, h, d = getwhd(box)
- tobesaved[name] = {
+ local spec = {
k = kind,
p = true,
c = column,
@@ -737,7 +770,7 @@ scanners.dosetpositionstrutkind = function() -- name
n = nofparagraphs > 0 and nofparagraphs or nil,
r2l = texgetcount("inlinelefttoright") == 1 or nil,
}
- ctxnode(new_latelua_node(function() enhance(tobesaved[name]) end))
+ ctx_latelua { action = enhance, specification = spec }
end
function jobpositions.getreserved(tag,n)
@@ -1377,6 +1410,11 @@ scanners.markregionboxtaggedkind = function() -- box tag kind
scaninteger(),scandimen(),scandimen(),scandimen(),scandimen())
end
+scanners.reservedautoregiontag = function()
+ nofregions = nofregions + 1
+ context(f_region(nofregions))
+end
+
-- statistics (at least for the moment, when testing)
-- statistics.register("positions", function()
diff --git a/tex/context/base/mkiv/anch-pos.mkiv b/tex/context/base/mkiv/anch-pos.mkiv
index ab199eb1e..fbebb5f17 100644
--- a/tex/context/base/mkiv/anch-pos.mkiv
+++ b/tex/context/base/mkiv/anch-pos.mkiv
@@ -155,7 +155,7 @@
\def\anch_positions_set_data_indeed#1#2#3#4%
{\anch_positions_initialize
- \hbox
+ \hbox % \hpack
{\edef\currentposition{#1}%
\dosetpositionwhd\currentposition{#2}{#3}{#4}% already \the\dimexpr
\anch_positions_trace_left
@@ -177,7 +177,7 @@
\def\anch_positions_set_box_finish#1%
{\anch_positions_initialize
- \hbox to \wd\nextbox
+ \hbox to \wd\nextbox % \hpack
{\edef\currentposition{#1}%
\dosetpositionbox\currentposition\nextbox
\anch_positions_trace_left
@@ -198,7 +198,7 @@
\def\anch_positions_set_strut_yes#1%
{\anch_positions_initialize
- \hbox to \zeropoint
+ \hbox to \zeropoint % \hpack
{\edef\currentposition{#1}%
\dosetpositionstrut\currentposition
\anch_positions_trace_left
@@ -215,7 +215,7 @@
\def\anch_positions_set_strut_kind_yes#1#2%
{\anch_positions_initialize
- \hbox to \zeropoint
+ \hbox to \zeropoint % \hpack
{\edef\currentposition{#1}%
\dosetpositionstrutkind\currentposition{#2}%
\anch_positions_trace_left
@@ -235,7 +235,7 @@
\def\anch_positions_set_plus_indeed#1#2#3#4#5%
{\anch_positions_initialize
- \hbox % just package
+ \hbox % \hpack
{\edef\currentposition{#1}%
\dosetpositionplus\currentposition{#2}{#3}{#4}{#5}% already \the\dimexpr
\anch_positions_trace_right
@@ -257,7 +257,7 @@
\def\anch_positions_set_plus_yes_finish#1#2%
{\anch_positions_initialize
- \hbox to \nextboxwd
+ \hbox to \nextboxwd % \hpack
{\edef\currentposition{#1}%
\dosetpositionplus\currentposition{\wd\nextbox}{\ht\nextbox}{\dp\nextbox}{#2}%
\anch_positions_trace_right
@@ -296,7 +296,7 @@
{\clf_markregionbox#1\relax}
\unexpanded\def\anch_mark_flow_box#1% will be extended / renamed
- {\hbox\bgroup
+ {\hpack\bgroup % \hpack
\global\advance\c_anch_text\plusone
\clf_markregionboxtagged#1{textarea:\the\c_anch_text}%
\box#1%
@@ -330,6 +330,8 @@
#6\relax % bottomoffset
\fi}
+\def\reservedautoregiontag{\clf_reservedautoregiontag}
+
%D We can copy a position with:
%D
%D \starttyping
@@ -393,7 +395,7 @@
{\the\t_anch_positions_tracers}
\unexpanded\def\enableparpositions % global
- {\global\let\registerparoptions\doregisterparoptions
+ {\glet\registerparoptions\doregisterparoptions
\global\positioningtrue}
\let\disableparpositions\relax
diff --git a/tex/context/base/mkiv/anch-snc.lua b/tex/context/base/mkiv/anch-snc.lua
new file mode 100644
index 000000000..8006f3bd6
--- /dev/null
+++ b/tex/context/base/mkiv/anch-snc.lua
@@ -0,0 +1,271 @@
+if not modules then modules = { } end modules ['anch-snc'] = {
+ version = 1.001,
+ comment = "companion to anch-snc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+function mp.xxOverlayRegion()
+ local r = tokens.getters.macro("m_overlay_region")
+ mp.quoted('"'.. r .. '"')
+-- mp.print('"'.. r .. '"')
+end
+
+-- use factors as in mlib-int.lua
+
+local tonumber, next, setmetatable = tonumber, next, setmetatable
+local concat, sort, remove, copy = table.concat, table.sort, table.remove, table.copy
+local match, find = string.match, string.find
+local lpegmatch = lpeg.match
+
+local setmetatableindex = table.setmetatableindex
+
+local factor = number.dimenfactors.bp
+local mpprint = mp.print
+local mpnumeric = mp.numeric
+local mppoints = mp.points
+local texgetdimen = tex.getdimen
+
+local p_number = lpeg.patterns.cardinal/tonumber
+local p_space = lpeg.patterns.whitespace^0
+local p_tag = lpeg.P("syncpos:") * p_number * lpeg.P(":") * p_number
+local p_option = p_number -- for now
+ * ((lpeg.P(",") * p_space * lpeg.P("reset") * lpeg.Cc(true)) + lpeg.Cc(false))
+
+local list = { }
+local colors = setmetatableindex("table")
+
+local kinds = {
+ above = 1,
+ continue = 2,
+ nothing = 3,
+ normal = 4,
+ below = 5,
+}
+
+local allentries = setmetatableindex(function(t,category)
+ setmetatable(t,nil)
+ for tag, pos in next, job.positions.collected do
+ local c, n = lpegmatch(p_tag,tag)
+ if c then
+ local tc = t[c]
+ if tc then
+ tc[n] = pos
+ else
+ t[c] = { [n] = pos }
+ end
+ end
+ end
+ for k, list in next, t do
+ sort(list,function(a,b)
+ local ap = a.p
+ local bp = b.p
+ if ap == bp then
+ return b.y < a.y
+ else
+ return ap < bp
+ end
+ end)
+ list.start = 1
+ end
+ setmetatableindex(t,"table")
+ return t[category]
+end)
+
+local lastdone = { }
+
+function mp.sync_collect(category,realpage,useregion)
+ local all = allentries[category]
+ local m = 0
+ local n = #all
+ list = { }
+ if useregion then
+ -- successive can be optimized when we sort by region
+ local start = 1
+ local done = false
+ local last, rtop, rbot
+ for i=start,n do
+ local pos = all[i]
+ local p = pos.p
+ local r = pos.r
+ if r == useregion then
+ if not done then
+ local region = job.positions.collected[r]
+ list.region = region
+ list.page = region
+ rtop = (region.y or 0) + (region.h or 0)
+ rbot = (region.y or 0) - (region.d or 0)
+ last = { kind = "nothing", top = rtop, bottom = 0, task = 0 }
+ m = m + 1 ; list[m] = last
+ done = true
+ end
+ local top = pos.y + pos.h
+ last.bottom = top
+ local task, reset = lpegmatch(p_option,pos.e)
+ last = { kind = "normal", top = top, bottom = 0, task = task }
+ m = m + 1 ; list[m] = last
+ end
+ end
+ if done then
+ last.bottom = rbot
+ end
+ else
+ local start = all.start or 1
+ local done = false
+ local last, rtop, rbot, ptop, pbot
+ for i=start,n do
+ local pos = all[i]
+ local p = pos.p
+ if p == realpage then
+ if not done then
+ local region = job.positions.collected[pos.r]
+ local page = job.positions.collected["page:"..realpage] or region
+ list.region = region
+ list.page = page
+ rtop = (region.y or 0) + (region.h or 0)
+ rbot = (region.y or 0) - (region.d or 0)
+ ptop = (page .y or 0) + (page .h or 0)
+ pbot = (page .y or 0) - (page .d or 0)
+ last = { kind = "above", top = ptop, bottom = rtop, task = 0 }
+ m = m + 1 ; list[m] = last
+ if i > 1 then
+ local task, reset = lpegmatch(p_option,all[i-1].e)
+ last = { kind = "continue", top = rtop, bottom = 0, task = task }
+ m = m + 1 ; list[m] = last
+ else
+ last = { kind = "nothing", top = rtop, bottom = 0, task = 0 }
+ m = m + 1 ; list[m] = last
+ end
+ done = true
+ end
+ local top = pos.y + pos.h
+ last.bottom = top
+ local task, reset = lpegmatch(p_option,pos.e)
+ if reset then
+ local l = list[2]
+ l.kind = "nothing"
+ l.task = 0
+ end
+ last = { kind = "normal", top = top, bottom = 0, task = task }
+ m = m + 1 ; list[m] = last
+ elseif p > realpage then
+ all.start = i -- tricky, only for page
+ break
+ end
+ end
+ if done then
+ last.bottom = rbot
+ last = { kind = "below", top = rbot, bottom = pbot, task = 0 }
+ m = m + 1 ; list[m] = last
+ lastdone[category] = {
+ { kind = "above", top = ptop, bottom = rtop, task = 0 },
+ { kind = "continue", top = rtop, bottom = rbot, task = list[#list-1].task }, -- lasttask
+ { kind = "below", top = rbot, bottom = pbot, task = 0 },
+ region = list.region,
+ page = list.page,
+ }
+ else
+ local l = lastdone[category]
+ if l then
+ list = copy(l) -- inefficient, mayb emetatable for region/page
+ m = 3
+ end
+ end
+ end
+ mpnumeric(m)
+end
+
+function mp.sync_extend()
+ local n = #list
+ if n > 0 then
+ for i=1,n do
+ local l = list[i]
+ local k = l.kind
+ if k == "nothing" then
+ local ll = list[i+1]
+ if ll and ll.kind == "normal" then
+ ll.top = l.top
+ remove(list,i)
+ n = #list
+ break
+ end
+ end
+ end
+ end
+ mpnumeric(n)
+end
+
+function mp.sync_prune()
+ local n = #list
+ if n > 0 then
+ if list[1].kind == "above" then
+ remove(list,1)
+ end
+ if list[1].kind == "nothing" then
+ remove(list,1)
+ end
+ if list[#list].kind == "below" then
+ remove(list,#list)
+ end
+ n = #list
+ end
+ mpnumeric(n)
+end
+
+function mp.sync_collapse()
+ local n = #list
+ if n > 0 then
+ local m = 0
+ local p = nil
+ for i=1,n do
+ local l = list[i]
+ local t = l.task
+ if p == t then
+ list[m].bottom = l.bottom
+ else
+ m = m + 1
+ list[m] = l
+ end
+ p = t
+ end
+ for i=n,m+1,-1 do
+ list[i] = nil
+ end
+ n = m
+ end
+ mpnumeric(n)
+end
+
+function mp.sync_set_color(category,n,v)
+ colors[category][n] = v
+end
+
+function mp.sync_get_color(category,n)
+ mpprint(colors[category][n])
+end
+
+-- function mp.sync_get_size () mpnumeric(#list) end
+-- function mp.sync_get_top (n) mppoints (list[n].top) end
+-- function mp.sync_get_bottom(n) mppoints (list[n].bottom) end
+-- function mp.sync_get_kind (n) mpnumeric(kinds[list[n].kind]) end
+-- function mp.sync_get_task (n) mpnumeric(list[n].task) end
+
+-- function mp.sync_get_x() mppoints(list.page.x or 0) end
+-- function mp.sync_get_y() mppoints(list.page.y or 0) end
+-- function mp.sync_get_w() mppoints(list.page.w or 0) end
+-- function mp.sync_get_h() mppoints(list.page.h or 0) end
+-- function mp.sync_get_d() mppoints(list.page.d or 0) end
+
+function mp.sync_get_size () mpnumeric(#list) end
+function mp.sync_get_top (n) mpnumeric(list[n].top * factor) end
+function mp.sync_get_bottom(n) mpnumeric(list[n].bottom * factor) end
+function mp.sync_get_kind (n) mpnumeric(kinds[list[n].kind]) end
+function mp.sync_get_task (n) mpnumeric(list[n].task) end
+
+function mp.sync_get_x() mpnumeric((list.page.x or 0)*factor) end
+function mp.sync_get_y() mpnumeric((list.page.y or 0)*factor) end
+function mp.sync_get_w() mpnumeric((list.page.w or 0)*factor) end
+function mp.sync_get_h() mpnumeric((list.page.h or 0)*factor) end
+function mp.sync_get_d() mpnumeric((list.page.d or 0)*factor) end
diff --git a/tex/context/base/mkiv/anch-snc.mkiv b/tex/context/base/mkiv/anch-snc.mkiv
index 3e99da8a6..5f0246155 100644
--- a/tex/context/base/mkiv/anch-snc.mkiv
+++ b/tex/context/base/mkiv/anch-snc.mkiv
@@ -1,6 +1,6 @@
%D \module
%D [ file=anch-snc,
-%D version=2003.12.01,
+%D version=2003.12.01, % actually 1999 so real old
%D title=\CONTEXT\ Anchoring Macros,
%D subtitle=Synchronization,
%D author=Hans Hagen,
@@ -11,151 +11,42 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-% this can be optimized (will do when used again)
+%D The original is in the mkii file. It does more at the \TEX\ end and
+%D has some more magic. If we really need that I'll add it. After all,
+%D in mkiv we can do things different.
+
+%D TODO: bleed : + left , minus right oro check if it touches page ... autobleed
\writestatus{loading}{ConTeXt Anchoring Macros / Synchronization}
+\registerctxluafile{anch-snc}{}
+
\unprotect
-\ifx\s!num \undefined \def\s!num {num} \fi
-\ifx\s!set \undefined \def\s!set {set} \fi
-\ifx\s!reset \undefined \def\s!reset {reset} \fi
-\ifx\s!preset \undefined \def\s!preset {preset} \fi
-\ifx\s!syncpos\undefined \def\s!syncpos{syncpos} \fi
+\ifx\??syncposcounter\undefined \installcorenamespace{syncposcounter} \fi
+\ifx\s!syncpos \undefined \def\s!syncpos {syncpos} \fi
+
+\let\c_sync_n\relax
\unexpanded\def\definesyncpositions[#1]%
- {\ifcsname\s!num:\s!syncpos:#1\endcsname \else
- \global\let\flushsyncpositions\doflushsyncpositions % only when used
- \global\let\flushsyncresets \doflushsyncresets
- \global\let\flushsyncpresets \doflushsyncpresets
- \expandafter\newcount\csname\s!num:\s!syncpos:#1\endcsname
- \doglobal\appendtoksonce\csname\s!reset :\s!syncpos:#1\endcsname\to\resetsyncpositions
- \doglobal\appendtoksonce\csname\s!preset:\s!syncpos:#1\endcsname\to\presetsyncpositions
-% to be tested:
-% \doglobal\expandafter\appendtoksonce\csname\s!reset :\s!syncpos:#1\endcsname\to\resetsyncpositions
-% \doglobal\expandafter\appendtoksonce\csname\s!preset:\s!syncpos:#1\endcsname\to\presetsyncpositions
- \setgvalue{\s!syncpos:#1}{sync_n[#1] := 0 ;}%
- \setgvalue{\s!set:\s!syncpos:#1}{\dosetsyncpositions{#1}}%
+ {\ifcsname\??syncposcounter:#1\endcsname \else
+ \expandafter\newcount\csname\??syncposcounter:#1\endcsname
\fi}
-\def\syncposition
- {\dodoubleempty\dosyncposition}
-
-\def\dosyncposition[#1][#2]%
- {\letgvalue{\s!reset :\s!syncpos:#1}\relax
- \letgvalue{\s!preset:\s!syncpos:#1}\relax
- \dontleavehmode
- \dodosyncposition{#1}{#2}\s!set
- \ignorespaces}
-
-\def\doifelselastsyncposition#1#2%
- {\doifelse{\lastsyncclass\lastsyncposition}{#1#2}}
-
-\let\doiflastsyncpositionelse\doifelselastsyncposition
+\unexpanded\def\syncposition
+ {\dodoubleempty\anch_sync_position}
-\def\dodosyncposition#1#2#3%
- {\letgvalue{\s!reset:\s!syncpos:#1}\relax
- \letgvalue{\s!preset:\s!syncpos:#1}\relax
- \ifcsname\s!syncpos:#1\endcsname
- \global\advance\csname\s!num:\s!syncpos:#1\endcsname\plusone
- \setsyncpositions{#1}%
- % option: geen w/h, alleen p 0 0 0 data
- \setpositionplus{\s!syncpos:#1:\the\csname\s!num:\s!syncpos:#1\endcsname}{#2}\hpack{\strut}%
+\def\anch_sync_position[#1][#2]% we could actually use par positions
+ {\dontleavehmode
+ \ifcsname\??syncposcounter:#1\endcsname
+ \let\c_sync_n\lastnamedcs
+ \global\advance\c_sync_n\plusone
+ \enabletextarearegistration
+ \setpositionplus{\s!syncpos:#1:\the\c_sync_n}{#2}\hpack{\strut}%
\else
\strut
- \fi}
-
-\def\setsyncpositions#1%
- {\enabletextarearegistration
- \getvalue {\s!set:\s!syncpos:#1}%
- \letgvalue{\s!set:\s!syncpos:#1}\relax}
-
-\def\dosetsyncpositions#1%
- {\startnointerference % removing out of sync can best be done in mp
- \!!dimena\maxdimen
- \!!counta\zerocount
- \!!countc\zerocount
- \doloop
- {\doifelseposition{\s!syncpos:#1:\recurselevel}
- {\!!dimenb\MPy{\s!syncpos:#1:\recurselevel}\relax
- \!!countb\MPp{\s!syncpos:#1:\recurselevel}\relax
- \ifnum\!!countb=\!!counta % same page
- \ifdim\!!dimenb>\!!dimena
- \donefalse % out of order nodes
- \else
- \donetrue % nodes in order
- \fi
- \else
- \donetrue % different page
- \fi
- \ifdone
- \!!counta\!!countb
- \!!dimena\!!dimenb
- \advance\!!countc\plusone
- \edef\!!stringa{[#1][\the\!!countc]:=}%
- \edef\!!stringc{\s!syncpos:#1:\the\!!countc}%
- \edef\!!stringd{\MPplus\!!stringc{1}{0}}%
- \setxvalue{\s!syncpos:#1}%
- {\getsyncpositions{#1}%
- sync_p \!!stringa \MPp \!!stringc ;
- sync_xy\!!stringa \MPxy\!!stringc ;
- sync_w \!!stringa \MPw \!!stringc ;
- sync_h \!!stringa \MPh \!!stringc ;
- sync_d \!!stringa \MPd \!!stringc ;
- \ifx\!!stringd\empty \else sync_t \!!stringa \MPplus\!!stringc{1}{0} ; \fi}%
- \fi}
- {\setxvalue{\s!syncpos:#1}%
- {\getsyncpositions{#1}%
- sync_n[#1] := \the\!!countc ;}
- \exitloop}}%
- \stopnointerference}
-
-\def\getsyncpositions#1%
- {\getvalue{\s!syncpos:#1}}
-
-\newtoks\resetsyncpositions
-\newtoks\presetsyncpositions
-
-\def\resyncposition {\dodoubleargument\doresyncposition}
-\def\presyncposition{\dodoubleargument\dopresyncposition}
-
-\def\dodoresyncposition #1#2{\dodosyncposition{#1}{#2}\s!reset}
-\def\dodopresyncposition#1#2{\dodosyncposition{#1}{#2}\s!preset}
-
-\def\doresyncposition [#1][#2]{\setxvalue{\s!reset :\s!syncpos:#1}{\noexpand\dodoresyncposition{#1}{#2}}}
-\def\dopresyncposition[#1][#2]{\setxvalue{\s!preset:\s!syncpos:#1}{\noexpand\dodopresyncposition{#1}{#2}}}
-
-\let\flushsyncpositions\relax
-
-\def\doflushsyncpositions % this order !
- {\begingroup
- \the\presetsyncpositions
- \the\resetsyncpositions
- \endgroup}
-
-\def\flushsyncxxsets#1%
- {\begingroup
- \setbox\scratchbox\hbox{\the#1}%
- \ifvoid\scratchbox\else
- \prewordbreak
- %\let\prewordbreak\relax % only once
- \smashbox\scratchbox
- \box\scratchbox
\fi
- \endgroup}
-
-\let\flushsyncresets \relax
-\let\flushsyncpresets\relax
-
-\def\doflushsyncresets {\flushsyncxxsets\resetsyncpositions }
-\def\doflushsyncpresets{\flushsyncxxsets\presetsyncpositions}
-
-% \appendtoks \flushsyncpositions \to \everypar
-% \appendtoks \flushsyncpositions \to \everyheadstart
-
-% \explicitneverypar -> in grid snapper, eerst testen
-%
-% \appendtoks \flushsyncpositions \to \neverypar
+ \ignorespaces}
\protect
@@ -163,41 +54,106 @@
\starttext
+% \setuppapersize[A4][A3]
+
+\setuplayout[location=middle]
+
\setupbodyfont[dejavu]
\definesyncpositions[1]
+\definesyncpositions[2]
+
+% \enabletrackers[metapost.lua]
+
+\startMPdefinitions
+ input "mp-asnc.mpiv" ;
+
+ SetSyncColor(1,0,"magenta") ;
+ SetSyncColor(1,1,"red") ;
+ SetSyncColor(1,2,"green") ;
+ SetSyncColor(1,3,"blue") ;
+ SetSyncColor(1,4,"yellow") ;
+
+ SetSyncColor(2,0,"magenta") ;
+ SetSyncColor(2,1,"red") ;
+ SetSyncColor(2,2,"green") ;
+ SetSyncColor(2,3,"blue") ;
+ SetSyncColor(2,4,"yellow") ;
+\stopMPdefinitions
+
+\startuseMPgraphic{sync1}
+ StartPage ;
+ StartSync(1) ;
+ SyncHOffset := 0 ;
+ SyncWidth := BackSpace - LeftMarginDistance;
+ CollectSyncDataPage ;
+ % ExtendSyncPaths ; % to top of text area
+ PruneSyncPaths ; % clip top / bottom
+ CollapseSyncPaths ;
+ MakeSyncPaths ;
+ % DrawSyncPaths ;
+ FillSyncPaths ;
+ StopSync ;
+ clip currentpicture to Page ;
+ setbounds currentpicture to Page ;
+ StopPage ;
+\stopuseMPgraphic
-\startuseMPgraphic{sync}
- StartPage ;
- \getsyncpositions{1} ;
- SyncThreshold := 2LineHeight ;
- SyncLeftOffset := -.5LeftMarginDistance ;
- % SetSyncThreshold(1,3,3LineHeight) ;
- SyncWidth := - (BackSpace + SyncLeftOffset) ;
- SetSyncColor(1,1,\MPcolor{red}) ;
- SetSyncColor(1,2,\MPcolor{green}) ;
- SetSyncColor(1,3,\MPcolor{blue}) ;
- SetSyncColor(1,4,\MPcolor{yellow}) ;
- PrepareSyncTasks(1,true,true,false) ;
- for i = 1 upto NOfSyncPaths :
- fill SyncPaths[i]
- withcolor TheSyncColor(CurrentSyncClass,sync_t[CurrentSyncClass][SyncTasks[i]]) ;
- endfor ;
- setbounds currentpicture to Page ;
- StopPage ;
+\startuseMPgraphic{sync2}
+ StartSync(2) ;
+ SyncHOffset := -1cm ;
+ SyncWidth := 1cm ;
+ CollectSyncDataRegion(OverlayRegion) ;
+ ExtendSyncPaths ; % to top of text area
+ MakeSyncPaths ;
+ FillSyncPaths ;
+ StopSync ;
+ clip currentpicture to OverlayBox leftenlarged 1cm;
+ setbounds currentpicture to OverlayBox ;
\stopuseMPgraphic
-\defineoverlay[tempoverlay][\useMPgraphic{sync}]
+\defineoverlay[tempoverlay1][\useMPgraphic{sync1}]
+\defineoverlay[tempoverlay2][\useMPgraphic{sync2}]
+
+\setupbackgrounds[page][background=tempoverlay1]
+
+\framed[region=yes,background=tempoverlay2,width=14cm,align=normal]{
+ \syncposition[2][1]\samplefile{ward}\endgraf
+ \syncposition[2][2]\samplefile{ward}\endgraf
+ \syncposition[2][3]\samplefile{ward}\endgraf
+}
+
+
+\vskip1cm \hskip1cm \framed[region=yes,background=tempoverlay2,width=16cm,align=normal]{
+ \syncposition[2][1]\samplefile{ward}\endgraf
+ \syncposition[2][2]\samplefile{ward}\endgraf
+ \syncposition[2][3]\samplefile{ward}\endgraf
+}
+
+\vskip1cm \hskip1cm \framed[region=yes,background=tempoverlay2,width=10cm,align=normal]{
+ \syncposition[2][1]\samplefile{ward}\endgraf
+ \syncposition[2][2]\samplefile{ward}\endgraf
+ \syncposition[2][3]\samplefile{ward}\endgraf
+}
-\setupbackgrounds[page][background=tempoverlay]
-\dorecurse {10} {
+\dorecurse {100} {
+% \dorecurse {1} {
+ \startchapter[title={Test #1}]
+ \syncposition[1][1,reset]\dorecurse{20}{\samplefile{ward}\endgraf}
+ \syncposition[1][2]\dorecurse {4}{\samplefile{ward}\endgraf}
+ \syncposition[1][3]\dorecurse {7}{\samplefile{ward}\endgraf}
+ \syncposition[1][4]\dorecurse {3}{\samplefile{ward}\endgraf}
+ \stopchapter
+}
+\dorecurse {100} {
+% \dorecurse {1} {
\startchapter[title={Test #1}]
- \syncposition[1][1] \dorecurse{10}{\input ward \endgraf}
- \syncposition[1][2] \dorecurse {4}{\input ward \endgraf}
- \syncposition[1][3] \dorecurse {7}{\input ward \endgraf}
- \syncposition[1][4] \dorecurse {3}{\input ward \endgraf}
+ \syncposition[1][1]\dorecurse{1}{\samplefile{ward}\endgraf}
+ \syncposition[1][2]\dorecurse{1}{\samplefile{ward}\endgraf}
+ \syncposition[1][3]\dorecurse{1}{\samplefile{ward}\endgraf}
+ \syncposition[1][4]\dorecurse{1}{\samplefile{ward}\endgraf}
\stopchapter
}
diff --git a/tex/context/base/mkiv/anch-tab.mkiv b/tex/context/base/mkiv/anch-tab.mkiv
index afa87c7b2..67afb22f7 100644
--- a/tex/context/base/mkiv/anch-tab.mkiv
+++ b/tex/context/base/mkiv/anch-tab.mkiv
@@ -84,8 +84,8 @@
\newcount \noftabpositions
\newtoks \posXCtoks
-\def\anch_tabulate_bpos{\bpos}
-\def\anch_tabulate_epos{\epos}
+\unexpanded\def\anch_tabulate_bpos{\bpos}
+\unexpanded\def\anch_tabulate_epos{\epos}
\installcorenamespace{positiontables}
@@ -134,15 +134,18 @@
{\anch_tables_append_GSC[#1:#1]}
\def\anch_tables_append_GSC[#1:#2:#3]%
- {\doglobal\appendtoks\anch_tables_process_GSC[#1:#2]\to\posXCtoks\NC}
+% {\doglobal\appendtoks\anch_tables_process_GSC[#1:#2]\to\posXCtoks\NC}
+ {\gtoksapp\posXCtoks{\anch_tables_process_GSC[#1:#2]}\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}
+ \doglobal\appendtoks\expandafter\anch_tabulate_epos\expandafter{\tbPOSprefix#1}\to\posXCtoks}
+% \xtoksapp\posXCtoks{\anch_tabulate_epos{\tbPOSprefix#1}}}
\def\anch_tables_indeed_GFC[#1]%
{\doglobal\appendtoks\anch_tables_delayed_GFC[#1]\to\posXCtoks\NC}
+% {\gtoksapp\posXCtoks{\anch_tables_delayed_GFC[#1]}\NC}
\def\anch_tables_delayed_GFC[#1]%
{\processcommalist[#1]\anch_tables_step_GFC}
@@ -156,9 +159,11 @@
\def\anch_tables_indeed_GTC[#1]%
{\doglobal\appendtoks\anch_tables_delayed_GTC[#1]\to\posXCtoks\NC}
+% {\gtoksapp\posXCtoks{\anch_tables_delayed_GTC[#1]}\NC}
\def\anch_tables_delayed_GTC[#1]%
{\doglobal\appendtoks\anch_tables_process_GTC[#1]\to\posXCtoks}
+% {\gtoksapp\posXCtoks{\anch_tables_process_GTC[#1]}\NC}
\def\anch_tables_process_GTC[#1]%
{\processcommalist[#1]\anch_tables_step_GTC}
@@ -207,10 +212,10 @@
\let\anch_tabulate_flush_epos\relax
-\def\anch_tabulate_bpos_indeed
+\unexpanded\def\anch_tabulate_bpos_indeed
{\bpos}
-\def\anch_tabulate_epos_indeed#1%
+\unexpanded\def\anch_tabulate_epos_indeed#1%
{\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
\epos{#1}%
\glet\anch_tabulate_flush_epos\relax
diff --git a/tex/context/base/mkiv/attr-col.lua b/tex/context/base/mkiv/attr-col.lua
index 28e63b177..5ea72c7e3 100644
--- a/tex/context/base/mkiv/attr-col.lua
+++ b/tex/context/base/mkiv/attr-col.lua
@@ -114,12 +114,16 @@ local data = colors.data
local values = colors.values
local registered = colors.registered
+local cmykrgbmode = 0 -- only for testing, already defined colors are not affected
+
local numbers = attributes.numbers
local list = attributes.list
registerstorage("attributes/colors/values", values, "attributes.colors.values")
registerstorage("attributes/colors/registered", registered, "attributes.colors.registered")
+directives.register("colors.cmykrgbmode", function(v) cmykrgbmode = tonumber(v) or 0 end)
+
local f_colors = {
rgb = formatters["r:%s:%s:%s"],
cmyk = formatters["c:%s:%s:%s:%s"],
@@ -148,8 +152,11 @@ end
local function cmyktorgb(c,m,y,k)
if not c then
return 0, 0, 0, 1
+ elseif cmykrgbmode == 1 then
+ local d = 1.0 - k
+ return 1.0 - min(1.0,c*d+k), 1.0 - min(1.0,m*d+k), 1.0 - min(1.0,y*d+k)
else
- return 1.0 - min(1.0,c+k), 1.0 - min(1.0,m+k), 1.0 - min(1.0,y+k)
+ return 1.0 - min(1.0,c +k), 1.0 - min(1.0,m +k), 1.0 - min(1.0,y +k)
end
end
@@ -295,7 +302,7 @@ function colors.spot(parent,f,d,p)
local v = values[n]
if v then
-- the via cmyk hack is dirty, but it scales better
- local c, m, y, k = p*v[6], p*v[7], p*v[8], p*v[8]
+ local c, m, y, k = p*v[6], p*v[7], p*v[8], p*v[9]
local r, g, b = cmyktorgb(c,m,y,k)
local s = cmyktogray(c,m,y,k)
return { 5, s, r, g, b, c, m, y, k, parent, f, d, p }
@@ -318,7 +325,7 @@ function colors.spot(parent,f,d,p)
c = c + p*v[6]
m = m + p*v[7]
y = y + p*v[8]
- k = k + p*v[8]
+ k = k + p*v[9]
done = true
end
end
@@ -361,10 +368,14 @@ local function reviver(data,n)
local gray = graycolor(v[2])
d = { gray, gray, gray, gray }
elseif model == 3 then
- local gray, rgb, cmyk = graycolor(v[2]), rgbcolor(v[3],v[4],v[5]), cmykcolor(v[6],v[7],v[8],v[9])
+ local gray = graycolor(v[2])
+ local rgb = rgbcolor(v[3],v[4],v[5])
+ local cmyk = cmykcolor(v[6],v[7],v[8],v[9])
d = { rgb, gray, rgb, cmyk }
elseif model == 4 then
- local gray, rgb, cmyk = graycolor(v[2]), rgbcolor(v[3],v[4],v[5]), cmykcolor(v[6],v[7],v[8],v[9])
+ local gray = graycolor(v[2])
+ local rgb = rgbcolor(v[3],v[4],v[5])
+ local cmyk = cmykcolor(v[6],v[7],v[8],v[9])
d = { cmyk, gray, rgb, cmyk }
elseif model == 5 then
local spot = spotcolor(v[10],v[11],v[12],v[13])
@@ -406,10 +417,29 @@ function colors.setmodel(name,weightgray)
weightgray = true
end
end
- colors.model = name -- global, not useful that way
- colors.default = models[name] or 1 -- global
- colors.weightgray = weightgray -- global
- return colors.default
+ local default = models[name] or 1
+
+ colors.model = name -- global, not useful that way
+ colors.default = default -- global
+ colors.weightgray = weightgray -- global
+
+ -- avoid selective checking is no need for it
+
+ local forced = colors.forced
+
+ if forced == nil then
+ -- unset
+ colors.forced = default
+ elseif forced == false then
+ -- assumed mixed
+ elseif forced ~= default then
+ -- probably mixed
+ colors.forced = false
+ else
+ -- stil the same
+ end
+
+ return default
end
function colors.register(name, colorspace, ...) -- passing 9 vars is faster (but not called that often)
diff --git a/tex/context/base/mkiv/attr-ini.lua b/tex/context/base/mkiv/attr-ini.lua
index 67faa9fc0..dd971afc1 100644
--- a/tex/context/base/mkiv/attr-ini.lua
+++ b/tex/context/base/mkiv/attr-ini.lua
@@ -62,7 +62,7 @@ ranges of numbers for them. Of course a the <l n='context'/> end a private attri
accessible too, so a private attribute can have a public appearance.</p>
--ldx]]--
-sharedstorage.attributes_last_private = sharedstorage.attributes_last_private or 127 -- very private (can become 15)
+sharedstorage.attributes_last_private = sharedstorage.attributes_last_private or 15 -- very private
sharedstorage.attributes_last_public = sharedstorage.attributes_last_public or 1024 -- less private
function attributes.private(name) -- at the lua end (hidden from user)
@@ -114,7 +114,8 @@ local function showlist(what,list)
local a = list.next
local i = 0
while a do
- local number, value = a.number, a.value
+ local number = a.number
+ local value = a.value
i = i + 1
report_attribute("%S %2i: attribute %3i, value %4i, name %a",what,i,number,value,names[number])
a = a.next
diff --git a/tex/context/base/mkiv/attr-ini.mkiv b/tex/context/base/mkiv/attr-ini.mkiv
index d537cebfa..3792b1c63 100644
--- a/tex/context/base/mkiv/attr-ini.mkiv
+++ b/tex/context/base/mkiv/attr-ini.mkiv
@@ -24,6 +24,7 @@
\installcorenamespace{attributecount} % the counter representing the attribute (attrdef'd)
\installcorenamespace{attributeid} % the internal number
\installcorenamespace{attributestack} % the attribute specific stack
+\installcorenamespace{attributepickup}
\unexpanded\def\pushattribute#1%
{\global\advance\csname\??attributestack\string#1\endcsname\plusone
@@ -40,12 +41,15 @@
\newtoks \t_attr_list_global
\newtoks \t_attr_list_local
+\newtoks \t_attr_list_pickup
\newtoks \t_attr_list_nomath
\ifdefined \s!global \else \def\s!global {global} \fi % for metatex % or hard check later
\ifdefined \s!public \else \def\s!public {public} \fi % for metatex % or hard check later
\ifdefined \s!private \else \def\s!private {private} \fi % for metatex % or hard check later
\ifdefined \s!attribute \else \def\s!attribute{attribute} \fi % for metatex % or hard check later
+\ifdefined \s!pickup \else \def\s!pickup {pickup} \fi % for metatex % or hard check later
+\ifdefined \s!forget \else \def\s!forget {forget} \fi % for metatex % or hard check later
\unexpanded\def\defineattribute {\dodoubleempty\attr_basics_define}
\unexpanded\def\definesystemattribute{\dodoubleempty\attr_basics_define_system}
@@ -53,6 +57,8 @@
\def\attr_basics_define {\attr_basics_define_indeed\s!public}
\def\attr_basics_define_system{\attr_basics_define_indeed\s!private}
+ % here public means 'visible' so it's not to be confused with 'public' at the lua end
+
\def\attr_basics_define_indeed#1[#2][#3]%
{\ifcsname\??attributecount#2\endcsname\else
\scratchcounter\clf_defineattribute{#2}{#1}\relax
@@ -62,15 +68,33 @@
\csname\??attributeid#2\endcsname\scratchcounter
% some attributes are always global
\doifelseinset\s!global{#3}%
- {\appendetoks\csname\??attributecount#2\endcsname\attributeunsetvalue\to\t_attr_list_global}%
- {\appendetoks\csname\??attributecount#2\endcsname\attributeunsetvalue\to\t_attr_list_local }%
+ {\etoksapp\t_attr_list_global{\csname\??attributecount#2\endcsname\attributeunsetvalue}}%
+ {\etoksapp\t_attr_list_local {\csname\??attributecount#2\endcsname\attributeunsetvalue}}%
\doifinset\s!nomath{#3}%
- {\appendetoks\csname\??attributecount#2\endcsname\attributeunsetvalue\to\t_attr_list_nomath}%
- % here public means 'visible' so it's not to be confused with 'public' at the lua end
+ {\etoksapp\t_attr_list_nomath{\csname\??attributecount#2\endcsname\attributeunsetvalue}}%
\doifinset\s!public{#3}%
{\expandafter\let\csname#2\s!attribute\expandafter\endcsname\csname\??attributeid#2\endcsname}%
+ \doifinset\s!pickup{#3}%
+ {\expandafter\newconstant\csname\??attributepickup#2\endcsname
+ \csname\??attributepickup#2\endcsname\attributeunsetvalue
+ \etoksapp\t_attr_list_pickup{\csname\??attributecount#2\endcsname\csname\??attributepickup#2\endcsname}%
+ \ifcsname#2\s!attribute\endcsname
+ \expandafter\edef\csname\s!pickup#2\s!attribute\endcsname
+ {\csname\??attributepickup#2\endcsname\csname\??attributecount#2\endcsname}%
+ \expandafter\edef\csname\s!forget#2\s!attribute\endcsname
+ {\csname\??attributepickup#2\endcsname\attributeunsetvalue}%
+ \fi}%
\fi}
+\unexpanded\def\pickupattributes
+ {\the\t_attr_list_pickup\relax}
+
+% \unexpanded\def\pickupattribute#1%
+% {\csname\??attributecount#1\endcsname\csname\??attributepickup#1\endcsname}
+
+% \unexpanded\def\pickupattributelater#1%
+% {\csname\??attributepickup#1\endcsname\csname\??attributecount#1\endcsname}
+
\unexpanded\def\newattribute#1%
{\attr_basics_define_indeed\s!public[\csstring#1][]%
\expandafter\let\expandafter#1\csname\??attributeid\csstring#1\endcsname}
@@ -84,8 +108,8 @@
\let\dompattribute\gobbletwoarguments
-\unexpanded\def\resetglobalattributes{\the\t_attr_list_global}
-\unexpanded\def\resetlocalattributes {\the\t_attr_list_local }
+\unexpanded\def\resetglobalattributes{\the\t_attr_list_global\attribute\zerocount\zerocount}
+\unexpanded\def\resetlocalattributes {\the\t_attr_list_local \attribute\zerocount\zerocount}
\let\resetallattributes\resetlocalattributes
diff --git a/tex/context/base/mkiv/back-exp.lua b/tex/context/base/mkiv/back-exp.lua
index b18679fa2..f5035d3cf 100644
--- a/tex/context/base/mkiv/back-exp.lua
+++ b/tex/context/base/mkiv/back-exp.lua
@@ -37,7 +37,7 @@ local next, type, tonumber = next, type, tonumber
local sub, gsub = string.sub, string.gsub
local validstring = string.valid
local lpegmatch = lpeg.match
-local utfchar, utfvalues = utf.char, utf.values
+local utfchar, utfvalues, utflen = utf.char, utf.values, utf.len
local concat, insert, remove, merge, sort = table.concat, table.insert, table.remove, table.merge, table.sort
local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys
local formatters = string.formatters
@@ -46,6 +46,7 @@ local replacetemplate = utilities.templates.replace
local trace_export = false trackers.register ("export.trace", function(v) trace_export = v end)
local trace_spacing = false trackers.register ("export.trace.spacing", function(v) trace_spacing = v end)
+local trace_detail = false trackers.register ("export.trace.detail", function(v) trace_detail = v end)
local less_state = false directives.register("export.lessstate", function(v) less_state = v end)
local show_comment = true directives.register("export.comment", function(v) show_comment = v end)
@@ -67,6 +68,7 @@ local attributes = attributes
local variables = interfaces.variables
local v_yes = variables.yes
local v_no = variables.no
+local v_xml = variables.xml
local v_hidden = variables.hidden
local implement = interfaces.implement
@@ -82,56 +84,8 @@ local fontchar = fonts.hashes.characters
local fontquads = fonts.hashes.quads
local languagenames = languages.numbers
-local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
-local listcodes = nodes.listcodes
-
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local glyph_code = nodecodes.glyph
-local glue_code = nodecodes.glue
-local kern_code = nodecodes.kern
-local disc_code = nodecodes.disc
-
-local userskip_code = skipcodes.userskip
-local rightskip_code = skipcodes.rightskip
-local parfillskip_code = skipcodes.parfillskip
-local spaceskip_code = skipcodes.spaceskip
-local xspaceskip_code = skipcodes.xspaceskip
-
-local line_code = listcodes.line
-
local texgetcount = tex.getcount
-local privateattribute = attributes.private
-local a_characters = privateattribute('characters')
-local a_exportstatus = privateattribute('exportstatus')
-local a_tagged = privateattribute('tagged')
-local a_taggedpar = privateattribute("taggedpar")
-local a_image = privateattribute('image')
-local a_reference = privateattribute('reference')
-local a_textblock = privateattribute("textblock")
-
-local nuts = nodes.nuts
-local tonut = nuts.tonut
-
-local getnext = nuts.getnext
-local getsubtype = nuts.getsubtype
-local getfont = nuts.getfont
-local getdisc = nuts.getdisc
-local getcomponents = nuts.getcomponents
-local getlist = nuts.getlist
-local getid = nuts.getid
-local getattr = nuts.getattr
-local setattr = nuts.setattr -- maybe use properties
-local isglyph = nuts.isglyph
-local getkern = nuts.getkern
-local getwidth = nuts.getwidth
-
-
-local traverse_id = nuts.traverse_id
-local traverse_nodes = nuts.traverse
-
local references = structures.references
local structurestags = structures.tags
local taglist = structurestags.taglist
@@ -167,7 +121,7 @@ local currentparagraph = nil
local noftextblocks = 0
-local hyphencode = 0xAD
+----- hyphencode = 0xAD
local hyphen = utfchar(0xAD) -- todo: also emdash etc
local tagsplitter = structurestags.patterns.splitter
----- colonsplitter = lpeg.splitat(":")
@@ -554,6 +508,8 @@ do
local fields = { "title", "subtitle", "author", "keywords", "url", "version" }
+ local ignoredelements = false
+
local function checkdocument(root)
local data = root.data
if data then
@@ -580,6 +536,9 @@ do
elseif tg == "ignore" then
di.element = ""
checkdocument(di)
+ elseif ignoredelements and ignoredelements[tg] then
+ di.element = ""
+ checkdocument(di)
else
checkdocument(di) -- new, else no noexport handling
end
@@ -609,6 +568,64 @@ do
checkdocument(di)
end
+ implement {
+ name = "ignoretagsinexport",
+ arguments = "string",
+ actions = function(list)
+ for tag in string.gmatch(list,"[a-z]+") do
+ if ignoredelements then
+ ignoredelements[tag] = true
+ else
+ ignoredelements = { [tag] = true }
+ end
+ end
+ end,
+ }
+
+end
+
+do
+
+ local marginanchors = { }
+ local margincontent = { }
+
+ implement {
+ name = "settagmargintext",
+ arguments = "integer",
+ actions = function(n)
+ marginanchors[locatedtag("margintext")] = n
+ end
+ }
+
+ implement {
+ name = "settagmarginanchor",
+ arguments = "integer",
+ actions = function(n)
+ marginanchors[locatedtag("marginanchor")] = n
+ end
+ }
+
+ function checks.margintext(di)
+ local i = marginanchors[di.fulltag]
+ margincontent[i] = di
+ end
+
+ function checks.marginanchor(di)
+ local i = marginanchors[di.fulltag]
+ local d = margincontent[i]
+ --
+ di.attribute = d.attribute
+ di.data = d.data
+ di.detail = d.detail
+ di.element = d.element
+ di.fulltag = d.fulltag
+ di.nature = d.nature
+ di.samepar = true
+ di.tg = d.tg
+ --
+ d.skip = "ignore"
+ end
+
end
do
@@ -922,7 +939,8 @@ evaluators.special = function(di,var)
end
end
-local referencehash = { }
+local referencehash = { }
+local destinationhash = { }
do
@@ -1040,10 +1058,37 @@ do
end
end
+ local function reference(di,element,n,fulltag)
+ local destination = destinationhash[fulltag]
+ if destination then
+ local d = structures.references.internals[destination]
+ if d then
+ addreference(di,d.references)
+ return true
+ else
+ return false
+ end
+ else
+ local data = di.data
+ if data then
+ for i=1,#data do
+ local di = data[i]
+ if di then
+ local fulltag = di.fulltag
+ if fulltag and reference(di,element,n,fulltag) then
+ return true
+ end
+ end
+ end
+ end
+ end
+ end
+
extras.adddestination = adddestination
extras.addreference = addreference
extras.link = link
+ extras.reference = reference
end
@@ -1243,22 +1288,21 @@ do
}
end
if ndata == 0 then
-root.skip = "comment" -- get rid of weird artefacts
-root.nota = "weird"
+ root.skip = "comment" -- get rid of weird artefacts
+ root.nota = "weird"
return
elseif ndata == 1 then
local d = data[1]
if not d or d == "" then
-root.skip = "comment"
+ root.skip = "comment"
return
elseif d.content then
return
else -- if ndata == 1 then
local tg = d.tg
--- if automathrows and roottg == "mrow" then
-if automathrows and (roottg == "mrow" or roottg == "mtext") then
+ if automathrows and (roottg == "mrow" or roottg == "mtext") then
-- maybe just always ! check spec first
--- or we can have chesks.* for each as we then can flatten
+ -- or we can have chesks.* for each as we then can flatten
if no_mrow[tg] then
root.skip = "comment"
end
@@ -1670,10 +1714,10 @@ if automathrows and (roottg == "mrow" or roottg == "mtext") then
end
function checks.mrow(di)
--- local d = di.data
--- if d then
--- checked(d)
--- end
+ -- local d = di.data
+ -- if d then
+ -- checked(d)
+ -- end
end
-- we can move more checks here
@@ -1760,6 +1804,25 @@ end
do
+ local registered = { }
+
+ function structurestags.setformulacontent(n)
+ registered[locatedtag("formulacontent")] = {
+ n = n,
+ }
+ end
+
+ function extras.formulacontent(di,element,n,fulltag)
+ local r = registered[fulltag]
+ if r then
+ setattribute(di,"n",r.n)
+ end
+ end
+
+end
+
+do
+
local registered = structures.sections.registered
local function resolve(di,element,n,fulltag)
@@ -1861,7 +1924,7 @@ do
end
end
- local function ignorebreaks(di,element,n,fulltag)
+ function extras.registerpages(di,element,n,fulltag) -- ignorebreaks
local data = di.data
for i=1,#data do
local d = data[i]
@@ -1871,7 +1934,7 @@ do
end
end
- local function ignorespaces(di,element,n,fulltag)
+ function extras.registerseparator(di,element,n,fulltag) -- ignorespaces
local data = di.data
for i=1,#data do
local d = data[i]
@@ -1882,9 +1945,6 @@ do
end
end
- extras.registerpages = ignorebreaks
- extras.registerseparator = ignorespaces
-
end
do
@@ -1991,6 +2051,41 @@ do
end
+do
+
+ local usedpublications = { }
+ local tagsindatasets = setmetatableindex("table")
+ local serialize = false
+
+ function structurestags.setpublication(dataset,tag,rendering)
+ usedpublications[locatedtag("publication")] = {
+ dataset = dataset,
+ tag = tag,
+ rendering = rendering
+ }
+ tagsindatasets[dataset][tag] = true
+ if not serialize then
+ structures.tags.registerextradata("btx",function()
+ local t = { "<btxdata>"}
+ for dataset, used in sortedhash(tagsindatasets) do
+ t[#t+1] = publications.converttoxml(dataset,true,false,true,false,true,true)
+ end
+ t[#t+1] = "</btxdata>"
+ return concat(t,"\n")
+ end)
+ end
+ end
+
+ function extras.publication(di,element,n,fulltag)
+ local hash = usedpublications[fulltag]
+ if hash then
+ setattribute(di,"dataset",hash.dataset)
+ setattribute(di,"tag",hash.tag)
+ end
+ end
+
+end
+
-- flusher
do
@@ -1998,7 +2093,7 @@ do
local f_detail = formatters[' detail="%s"']
local f_chain = formatters[' chain="%s"']
local f_index = formatters[' n="%s"']
- local f_spacing = formatters['<c n="%s">%s</c>']
+ local f_spacing = formatters['<c p="%s">%s</c>']
local f_empty_inline = formatters["<%s/>"]
local f_empty_mixed = formatters["%w<%s/>\n"]
@@ -2062,7 +2157,7 @@ do
local depth = 0
local inline = 0
- local function emptytag(result,embedded,element,nature,di) -- currently only break but at some point
+ local function emptytag(result,element,nature,di) -- currently only break but at some point
local a = di.attributes -- we might add detail etc
if a then -- happens seldom
if nature == "display" then
@@ -2111,7 +2206,7 @@ do
end
end
- local function begintag(result,embedded,element,nature,di,skip)
+ local function begintag(result,element,nature,di,skip)
local index = di.n
local fulltag = di.fulltag
local specification = specifications[fulltag] or { } -- we can have a dummy
@@ -2135,12 +2230,6 @@ do
-- ignore
else
- -- if embedded then
- -- if element == "math" then
- -- embedded[f_tagid(element,index)] = #result+1
- -- end
- -- end
-
local n = 0
local r = { } -- delay this
if detail then
@@ -2160,6 +2249,7 @@ do
n = n + 1
r[n] = f_index(index)
end
+ --
local extra = extras[element]
if extra then
extra(di,element,index,fulltag)
@@ -2181,8 +2271,14 @@ do
end
local a = di.attributes
if a then
+ if trace_spacing then
+ a.p = di.parnumber or 0
+ end
n = n + 1
r[n] = attributes(a)
+ elseif trace_spacing then
+ n = n + 1
+ r[n] = attributes { p = di.parnumber or 0 }
end
if n == 0 then
if nature == "inline" or inline > 0 then
@@ -2249,7 +2345,7 @@ do
end
end
- local function endtag(result,embedded,element,nature,di,skip)
+ local function endtag(result,element,nature,di,skip)
if skip == "comment" then
if show_comment then
if nature == "display" and (inline == 0 or inline == 1) then
@@ -2280,18 +2376,10 @@ do
inline = inline - 1
result[#result+1] = f_end_inline(namespaced[element])
end
-
- -- if embedded then
- -- if element == "math" then
- -- local id = f_tagid(element,di.n) -- index)
- -- local tx = concat(result,"",embedded[id],#result)
- -- embedded[id] = "<?xml version='1.0' standalone='yes'?>" .. "\n" .. tx
- -- end
- -- end
end
end
- local function flushtree(result,embedded,data,nature)
+ local function flushtree(result,data,nature)
local nofdata = #data
for i=1,nofdata do
local di = data[i]
@@ -2323,23 +2411,23 @@ do
if not element then
-- skip
elseif element == "break" then -- or element == "pagebreak"
- emptytag(result,embedded,element,nature,di)
+ emptytag(result,element,nature,di)
elseif element == "" or di.skip == "ignore" then
-- skip
else
if di.before then
- flushtree(result,embedded,di.before,nature)
+ flushtree(result,di.before,nature)
end
local natu = di.nature
local skip = di.skip
if di.breaknode then
- emptytag(result,embedded,"break","display",di)
+ emptytag(result,"break","display",di)
end
- begintag(result,embedded,element,natu,di,skip)
- flushtree(result,embedded,di.data,natu)
- endtag(result,embedded,element,natu,di,skip)
+ begintag(result,element,natu,di,skip)
+ flushtree(result,di.data,natu)
+ endtag(result,element,natu,di,skip)
if di.after then
- flushtree(result,embedded,di.after,nature)
+ flushtree(result,di.after,nature)
end
end
end
@@ -2360,19 +2448,25 @@ do
local di = data[i]
if not di then
-- skip
+ elseif di.skip == "ignore" then
+ -- skip (new)
elseif di.content then
- local parnumber = di.parnumber
- if prevnature == "inline" and prevparnumber and prevparnumber ~= parnumber then
- nofnewdata = nofnewdata + 1
- if trace_spacing then
- newdata[nofnewdata] = makebreaknode { type = "a", p = prevparnumber, n = parnumber }
- else
- newdata[nofnewdata] = makebreaknode()
+ if di.samepar then
+ prevparnumber = false
+ else
+ local parnumber = di.parnumber
+ if prevnature == "inline" and prevparnumber and prevparnumber ~= parnumber then
+ nofnewdata = nofnewdata + 1
+ if trace_spacing then
+ newdata[nofnewdata] = makebreaknode { type = "a", p = prevparnumber, n = parnumber }
+ else
+ newdata[nofnewdata] = makebreaknode()
+ end
end
+ prevelement = nil
+ prevparnumber = parnumber
end
- prevelement = nil
prevnature = "inline"
- prevparnumber = parnumber
nofnewdata = nofnewdata + 1
newdata[nofnewdata] = di
elseif not di.collapsed then
@@ -2383,39 +2477,51 @@ do
end
prevelement = element
prevnature = "display"
+ nofnewdata = nofnewdata + 1
+ newdata[nofnewdata] = di
elseif element == "" or di.skip == "ignore" then
-- skip
else
+ if di.samepar then
+ prevnature = "inline"
+ prevparnumber = false
+ else
+ local nature = di.nature
+ local parnumber = di.parnumber
+ if prevnature == "inline" and nature == "inline" and prevparnumber and prevparnumber ~= parnumber then
+ nofnewdata = nofnewdata + 1
+ if trace_spacing then
+ newdata[nofnewdata] = makebreaknode { type = "b", p = prevparnumber, n = parnumber }
+ else
+ newdata[nofnewdata] = makebreaknode()
+ end
+ end
+ prevnature = nature
+ prevparnumber = parnumber
+ end
+ prevelement = element
+ breaktree(di,tree,element)
+ nofnewdata = nofnewdata + 1
+ newdata[nofnewdata] = di
+ end
+ else
+ if di.samepar then
+ prevnature = "inline"
+ prevparnumber = false
+ else
local nature = di.nature
local parnumber = di.parnumber
if prevnature == "inline" and nature == "inline" and prevparnumber and prevparnumber ~= parnumber then
nofnewdata = nofnewdata + 1
if trace_spacing then
- newdata[nofnewdata] = makebreaknode { type = "b", p = prevparnumber, n = parnumber }
+ newdata[nofnewdata] = makebreaknode { type = "c", p = prevparnumber, n = parnumber }
else
newdata[nofnewdata] = makebreaknode()
end
end
prevnature = nature
prevparnumber = parnumber
- prevelement = element
- breaktree(di,tree,element)
- end
- nofnewdata = nofnewdata + 1
- newdata[nofnewdata] = di
- else
- local nature = di.nature
- local parnumber = di.parnumber
- if prevnature == "inline" and nature == "inline" and prevparnumber and prevparnumber ~= parnumber then
- nofnewdata = nofnewdata + 1
- if trace_spacing then
- newdata[nofnewdata] = makebreaknode { type = "c", p = prevparnumber, n = parnumber }
- else
- newdata[nofnewdata] = makebreaknode()
- end
end
- prevnature = nature
- prevparnumber = parnumber
nofnewdata = nofnewdata + 1
newdata[nofnewdata] = di
end
@@ -2447,6 +2553,8 @@ do
local cd = currentdata[j]
if not cd or cd == "" then
-- skip
+ elseif cd.skip == "ignore" then
+ -- skip
elseif cd.content then
if not currentpar then
-- add space ?
@@ -2593,9 +2701,9 @@ local function pop()
currentdepth = currentdepth - 1
if trace_export then
if top then
- report_export("%w</%s>",currentdepth,top)
+ report_export("%w</%s>",currentdepth,tree.tg)
else
- report_export("</%s>",top)
+ report_export("</%s>",tree.tg)
end
end
else
@@ -2701,7 +2809,7 @@ local function pushcontent(oldparagraph,newparagraph)
local nd = #td
td[nd+1] = { parnumber = oldparagraph or currentparagraph, content = content }
if trace_export then
- report_export("%w<!-- start content with length %s -->",currentdepth,#content)
+ report_export("%w<!-- start content with length %s -->",currentdepth,utflen(content))
report_export("%w%s",currentdepth,(gsub(content,"\n","\\n")))
report_export("%w<!-- stop content -->",currentdepth)
end
@@ -2746,27 +2854,119 @@ end
-- inserts ?
-local function collectresults(head,list,pat,pap) -- is last used (we also have currentattribute)
- local p
- for n in traverse_nodes(head) do
- local c, id = isglyph(n) -- 14: image, 8: literal (mp)
- if c then
- local at = getattr(n,a_tagged) or pat
- if not at then
- -- we need to tag the pagebody stuff as being valid skippable
- --
- -- report_export("skipping character: %C (no attribute)",n.char)
+local collectresults do -- too many locals otherwise
+
+ local nodecodes = nodes.nodecodes
+ local gluecodes = nodes.gluecodes
+ local listcodes = nodes.listcodes
+ local whatsitcodes = nodes.whatsitcodes
+
+ local subtypes = nodes.subtypes
+
+ local hlist_code = nodecodes.hlist
+ local vlist_code = nodecodes.vlist
+ local glyph_code = nodecodes.glyph
+ local glue_code = nodecodes.glue
+ local kern_code = nodecodes.kern
+ local disc_code = nodecodes.disc
+ local whatsit_code = nodecodes.whatsit
+ local localpar_code = nodecodes.localpar
+
+ local userskip_code = gluecodes.userskip
+ local rightskip_code = gluecodes.rightskip
+ local parfillskip_code = gluecodes.parfillskip
+ local spaceskip_code = gluecodes.spaceskip
+ local xspaceskip_code = gluecodes.xspaceskip
+
+ local linelist_code = listcodes.line
+
+ local userdefinedwhatsit_code = whatsitcodes.userdefined
+
+ local privateattribute = attributes.private
+ local a_image = privateattribute('image')
+ local a_reference = privateattribute('reference')
+ local a_destination = privateattribute('destination')
+ local a_characters = privateattribute('characters')
+ local a_exportstatus = privateattribute('exportstatus')
+ local a_tagged = privateattribute('tagged')
+ local a_taggedpar = privateattribute("taggedpar")
+ local a_textblock = privateattribute("textblock")
+
+ local inline_mark = nodes.pool.userids["margins.inline"]
+
+ local nuts = nodes.nuts
+
+ local getnext = nuts.getnext
+ local getdisc = nuts.getdisc
+ local getlist = nuts.getlist
+ local getid = nuts.getid
+ local getattr = nuts.getattr
+ local setattr = nuts.setattr -- maybe use properties
+ local isglyph = nuts.isglyph
+ local getkern = nuts.getkern
+ local getwidth = nuts.getwidth
+
+ local nexthlist = nuts.traversers.hlist
+ local nextnode = nuts.traversers.node
+
+ local function addtomaybe(maybewrong,c,case)
+ if trace_export then
+ report_export("%w<!-- possible paragraph mixup at %C case %i -->",currentdepth,c,case)
+ else
+ local s = formatters["%C"](c)
+ if maybewrong then
+ maybewrong[#maybewrong+1] = s
else
- -- we could add tonunicodes for ligatures (todo)
- local components = getcomponents(n)
- if components and (not characterdata[c] or overloads[c]) then -- we loose data
- collectresults(components,nil,at) -- this assumes that components have the same attribute as the glyph ... we should be more tolerant (see math)
+ maybewrong = { s }
+ end
+ return maybewrong
+ end
+ end
+
+ local function showmaybe(maybewrong)
+ if not trace_export then
+ report_export("fuzzy paragraph: % t",maybewrong)
+ end
+ end
+
+ local function showdetail(n,id,subtype)
+ local a = getattr(n,a_tagged)
+ local t = taglist[a]
+ local c = nodecodes[id]
+ local s = subtypes[id][subtype]
+ if a and t then
+ report_export("node %a, subtype %a, tag %a, element %a, tree '% t'",c,s,a,t.tagname,t.taglist)
+ else
+ report_export("node %a, subtype %a, untagged",c,s)
+ end
+ end
+
+ local function collectresults(head,list,pat,pap) -- is last used (we also have currentattribute)
+ local p
+ local localparagraph
+ local maybewrong
+ local pid
+ for n, id, subtype in nextnode, head do
+ if trace_detail then
+ showdetail(n,id,subtype)
+ end
+ if id == glyph_code then
+ local c, f = isglyph(n)
+ local at = getattr(n,a_tagged) or pat
+ if not at then
+ -- we need to tag the pagebody stuff as being valid skippable
+ --
+ -- report_export("skipping character: %C (no attribute)",n.char)
else
if last ~= at then
local tl = taglist[at]
+ local ap = getattr(n,a_taggedpar) or pap
+ if localparagraph and (not ap or ap < localparagraph) then
+ maybewrong = addtomaybe(maybewrong,c,1)
+ end
pushcontent()
- currentnesting = tl
- currentparagraph = getattr(n,a_taggedpar) or pap
+ currentnesting = tl
+ currentparagraph = ap
currentattribute = at
last = at
pushentry(currentnesting)
@@ -2780,6 +2980,11 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c
local t = tl.taglist
referencehash[t[#t]] = r -- fulltag
end
+ local d = getattr(n,a_destination)
+ if d then
+ local t = tl.taglist
+ destinationhash[t[#t]] = d -- fulltag
+ end
--
elseif last then
-- we can consider tagging the pars (lines) in the parbuilder but then we loose some
@@ -2792,12 +2997,15 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c
currentattribute = last
currentparagraph = ap
end
+ if localparagraph and (not ap or ap < localparagraph) then
+ maybewrong = addtomaybe(maybewrong,c,2)
+ end
if trace_export then
- report_export("%w<!-- processing glyph %C tagged %a) -->",currentdepth,c,last)
+ report_export("%w<!-- processing glyph %C tagged %a -->",currentdepth,c,last)
end
else
if trace_export then
- report_export("%w<!-- processing glyph %C tagged %a) -->",currentdepth,c,at)
+ report_export("%w<!-- processing glyph %C tagged %a -->",currentdepth,c,at)
end
end
local s = getattr(n,a_exportstatus)
@@ -2820,7 +3028,7 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c
currentcontent[nofcurrentcontent] = " "
end
else
- local fc = fontchar[getfont(n)]
+ local fc = fontchar[f]
if fc then
fc = fc and fc[c]
if fc then
@@ -2851,63 +3059,60 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c
end
end
end
- end
- elseif id == disc_code then -- probably too late
- local pre, post, replace = getdisc(n)
- if keephyphens then
- if pre and not getnext(pre) and isglyph(pre) == hyphencode then
- nofcurrentcontent = nofcurrentcontent + 1
- currentcontent[nofcurrentcontent] = hyphen
+ elseif id == disc_code then -- probably too late
+ local pre, post, replace = getdisc(n)
+ if keephyphens then
+ if pre and not getnext(pre) and isglyph(pre) == 0xAD then -- hyphencode then
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = hyphen
+ end
end
- end
- if replace then
- collectresults(replace,nil)
- end
- elseif id == glue_code then
- -- we need to distinguish between hskips and vskips
- local ca = getattr(n,a_characters)
- if ca == 0 then
- -- skip this one ... already converted special character (node-acc)
- elseif ca then
- local a = getattr(n,a_tagged) or pat
- if a then
- local c = specialspaces[ca]
- if last ~= a then
- local tl = taglist[a]
- if trace_export then
- report_export("%w<!-- processing space glyph %U tagged %a case 1 -->",currentdepth,ca,a)
- end
- pushcontent()
- currentnesting = tl
- currentparagraph = getattr(n,a_taggedpar) or pap
- currentattribute = a
- last = a
- pushentry(currentnesting)
- -- no reference check (see above)
- elseif last then
- local ap = getattr(n,a_taggedpar) or pap
- if ap ~= currentparagraph then
- pushcontent(currentparagraph,ap)
+ if replace then
+ collectresults(replace,nil)
+ end
+ elseif id == glue_code then
+ -- we need to distinguish between hskips and vskips
+ local ca = getattr(n,a_characters)
+ if ca == 0 then
+ -- skip this one ... already converted special character (node-acc)
+ elseif ca then
+ local a = getattr(n,a_tagged) or pat
+ if a then
+ local c = specialspaces[ca]
+ if last ~= a then
+ local tl = taglist[a]
+ if trace_export then
+ report_export("%w<!-- processing space glyph %U tagged %a case 1 -->",currentdepth,ca,a)
+ end
+ pushcontent()
+ currentnesting = tl
+ currentparagraph = getattr(n,a_taggedpar) or pap
+ currentattribute = a
+ last = a
pushentry(currentnesting)
- currentattribute = last
- currentparagraph = ap
- end
- if trace_export then
- report_export("%w<!-- processing space glyph %U tagged %a case 2 -->",currentdepth,ca,last)
+ -- no reference check (see above)
+ elseif last then
+ local ap = getattr(n,a_taggedpar) or pap
+ if ap ~= currentparagraph then
+ pushcontent(currentparagraph,ap)
+ pushentry(currentnesting)
+ currentattribute = last
+ currentparagraph = ap
+ end
+ if trace_export then
+ report_export("%w<!-- processing space glyph %U tagged %a case 2 -->",currentdepth,ca,last)
+ end
end
+ -- if somespace[currentcontent[nofcurrentcontent]] then
+ -- if trace_export then
+ -- report_export("%w<!-- removing space -->",currentdepth)
+ -- end
+ -- nofcurrentcontent = nofcurrentcontent - 1
+ -- end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = c
end
- -- if somespace[currentcontent[nofcurrentcontent]] then
- -- if trace_export then
- -- report_export("%w<!-- removing space -->",currentdepth)
- -- end
- -- nofcurrentcontent = nofcurrentcontent - 1
- -- end
- nofcurrentcontent = nofcurrentcontent + 1
- currentcontent[nofcurrentcontent] = c
- end
- else
- local subtype = getsubtype(n)
- if subtype == userskip_code then
+ elseif subtype == userskip_code then
if getwidth(n) > threshold then
if last and not somespace[currentcontent[nofcurrentcontent]] then
local a = getattr(n,a_tagged) or pat
@@ -2965,6 +3170,8 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c
if not keephyphens then
nofcurrentcontent = nofcurrentcontent - 1
end
+ elseif pid == disc_code then
+ -- go on .. tricky: we should mark the glyhs as coming from a disc
elseif not somespace[r] then
local a = getattr(n,a_tagged) or pat
if a == last then
@@ -2988,101 +3195,134 @@ local function collectresults(head,list,pat,pap) -- is last used (we also have c
end
end
elseif subtype == parfillskip_code then
- -- deal with paragaph endings (crossings) elsewhere and we quit here
+ -- deal with paragraph endings (crossings) elsewhere and we quit here
-- as we don't want the rightskip space addition
+ if maybewrong then
+ showmaybe(maybewrong)
+ end
return
end
- end
- elseif id == hlist_code or id == vlist_code then
- local ai = getattr(n,a_image)
- if ai then
- local at = getattr(n,a_tagged) or pat
- if nofcurrentcontent > 0 then
- pushcontent()
- pushentry(currentnesting) -- ??
- end
- pushentry(taglist[at]) -- has an index, todo: flag empty element
- if trace_export then
- report_export("%w<!-- processing image tagged %a",currentdepth,last)
- end
- last = nil
- currentparagraph = nil
- else
- -- we need to determine an end-of-line
- local list = getlist(n)
- if list then
+ elseif id == hlist_code or id == vlist_code then
+ local ai = getattr(n,a_image)
+ if ai then
local at = getattr(n,a_tagged) or pat
- collectresults(list,n,at)
- end
- end
- elseif id == kern_code then
- local kern = getkern(n)
- if kern > 0 then
- local limit = threshold
- if p and getid(p) == glyph_code then
- limit = fontquads[getfont(p)] / 4
+ if nofcurrentcontent > 0 then
+ pushcontent()
+ pushentry(currentnesting) -- ??
+ end
+ pushentry(taglist[at]) -- has an index, todo: flag empty element
+ if trace_export then
+ report_export("%w<!-- processing image tagged %a",currentdepth,last)
+ end
+ last = nil
+ currentparagraph = nil
+ else
+ -- we need to determine an end-of-line
+ local list = getlist(n)
+ if list then
+ -- todo: no par checking needed in math
+ local at = getattr(n,a_tagged) or pat
+ collectresults(list,n,at)
+ end
end
- if kern > limit then
- if last and not somespace[currentcontent[nofcurrentcontent]] then
- local a = getattr(n,a_tagged) or pat
- if a == last then
- if not somespace[currentcontent[nofcurrentcontent]] then
+ elseif id == kern_code then
+ local kern = getkern(n)
+ if kern > 0 then
+ local limit = threshold
+ if p then
+ local c, f = isglyph(p)
+ if c then
+ limit = fontquads[f] / 4
+ end
+ end
+ if kern > limit then
+ if last and not somespace[currentcontent[nofcurrentcontent]] then
+ local a = getattr(n,a_tagged) or pat
+ if a == last then
+ if not somespace[currentcontent[nofcurrentcontent]] then
+ if trace_export then
+ report_export("%w<!-- injecting spacing 8 (kern %p) -->",currentdepth,kern)
+ end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ end
+ elseif a then
+ -- e.g LOGO<space>LOGO
+ if trace_export then
+ report_export("%w<!-- processing kern, threshold %p, tag %s => %s -->",currentdepth,limit,last,a)
+ end
+ last = a
+ pushcontent()
if trace_export then
- report_export("%w<!-- injecting spacing 8 (kern %p) -->",currentdepth,kern)
+ report_export("%w<!-- injecting spacing 9 (kern %p) -->",currentdepth,kern)
end
nofcurrentcontent = nofcurrentcontent + 1
currentcontent[nofcurrentcontent] = " "
+ currentnesting = taglist[last]
+ pushentry(currentnesting)
+ currentattribute = last
end
- elseif a then
- -- e.g LOGO<space>LOGO
- if trace_export then
- report_export("%w<!-- processing kern, threshold %p, tag %s => %s -->",currentdepth,limit,last,a)
- end
- last = a
- pushcontent()
- if trace_export then
- report_export("%w<!-- injecting spacing 9 (kern %p) -->",currentdepth,kern)
- end
- nofcurrentcontent = nofcurrentcontent + 1
- currentcontent[nofcurrentcontent] = " "
- currentnesting = taglist[last]
- pushentry(currentnesting)
- currentattribute = last
end
end
end
+ elseif id == whatsit_code then
+ if subtype == userdefinedwhatsit_code then
+ -- similar to images, see above
+ local at = getattr(n,a_tagged)
+ if nofcurrentcontent > 0 then
+ pushcontent()
+ pushentry(currentnesting) -- ??
+ end
+ pushentry(taglist[at])
+ if trace_export then
+ report_export("%w<!-- processing anchor tagged %a",currentdepth,last)
+ end
+ last = nil
+ currentparagraph = nil
+ end
+ elseif not localparagraph and id == localpar_code and subtype == 0 then
+ localparagraph = getattr(n,a_taggedpar)
end
+ p = n
+ pid = id
+ end
+ if maybewrong then
+ showmaybe(maybewrong)
end
- p = n
end
-end
-function nodes.handlers.export(head) -- hooks into the page builder
- starttiming(treehash)
- if trace_export then
- report_export("%w<!-- start flushing page -->",currentdepth)
+ function nodes.handlers.export(head) -- hooks into the page builder
+ starttiming(treehash)
+ if trace_export then
+ report_export("%w<!-- start flushing page -->",currentdepth)
+ end
+ -- continueexport()
+ restart = true
+ collectresults(head)
+ if trace_export then
+ report_export("%w<!-- stop flushing page -->",currentdepth)
+ end
+ stoptiming(treehash)
+ return head
end
- -- continueexport()
- restart = true
- collectresults(tonut(head))
- if trace_export then
- report_export("%w<!-- stop flushing page -->",currentdepth)
+
+ function nodes.handlers.checkparcounter(p)
+ setattr(p,a_taggedpar,texgetcount("tagparcounter") + 1)
+ return p
end
- stoptiming(treehash)
- return head, true
-end
-function builders.paragraphs.tag(head)
- noftextblocks = noftextblocks + 1
- for n in traverse_id(hlist_code,tonut(head)) do
- local subtype = getsubtype(n)
- if subtype == line_code then
- setattr(n,a_textblock,noftextblocks)
- elseif subtype == glue_code or subtype == kern_code then -- no need to set fontkerns
- setattr(n,a_textblock,0)
+ function builders.paragraphs.tag(head)
+ noftextblocks = noftextblocks + 1
+ for n, subtype in nexthlist, head do
+ if subtype == linelist_code then
+ setattr(n,a_textblock,noftextblocks)
+ elseif subtype == glue_code or subtype == kern_code then -- no need to set fontkerns
+ setattr(n,a_textblock,0)
+ end
end
+ return false
end
- return false
+
end
do
@@ -3237,13 +3477,12 @@ local htmltemplate = [[
local function allcontent(tree,embed)
local result = { }
- local embedded = embed and { }
- flushtree(result,embedded,tree.data,"display") -- we need to collect images
+ flushtree(result,tree.data,"display") -- we need to collect images
result = concat(result)
-- no need to lpeg .. fast enough
result = gsub(result,"\n *\n","\n")
result = gsub(result,"\n +([^< ])","\n%1")
- return result, embedded
+ return result
end
-- local xhtmlpreamble = [[
@@ -3498,7 +3737,6 @@ local htmltemplate = [[
local basename = file.basename
local embedfile = false directives.register("export.embed",function(v) embedfile = v end)
- local embedmath = false
function structurestags.finishexport()
@@ -3508,12 +3746,18 @@ local htmltemplate = [[
return
end
+ local onlyxml = finetuning.export == v_xml
+
starttiming(treehash)
--
finishexport()
--
report_export("")
- report_export("exporting xml, xhtml and html files")
+ if onlyxml then
+ report_export("exporting xml, no other files")
+ else
+ report_export("exporting xml, xhtml, html and css files")
+ end
report_export("")
--
wrapups.collapsetree(tree)
@@ -3541,7 +3785,7 @@ local htmltemplate = [[
-- ./jobname-export/styles/jobname-images.css
-- ./jobname-export/styles/jobname-templates.css
- if type(askedname) ~= "string" or askedname == v_yes or askedname == "" then
+ if type(askedname) ~= "string" or askedname == "" then
askedname = tex.jobname
end
@@ -3609,6 +3853,74 @@ local htmltemplate = [[
stylefilebase,
}
+ local cssextra = cssfile and table.unique(settings_to_array(cssfile)) or { }
+
+ -- at this point we're ready for the content; the collector also does some
+ -- housekeeping and data collecting; at this point we still have an xml
+ -- representation that uses verbose element names and carries information in
+ -- attributes
+
+ local data = tree.data
+ for i=1,#data do
+ if data[i].tg ~= "document" then
+ data[i] = { }
+ end
+ end
+
+ local result = allcontent(tree,embedmath) -- embedfile is for testing
+
+ -- ugly but so be it:
+
+ local extradata = structures.tags.getextradata()
+ if extradata then
+ local t = { "" }
+ t[#t+1] = "<extradata>"
+ for name, action in sortedhash(extradata) do
+ t[#t+1] = action()
+ end
+ t[#t+1] = "</extradata>"
+ t[#t+1] = "</document>"
+ -- we use a function because otherwise we can have a bad capture index
+ result = gsub(result,"</document>",function()
+ return concat(t,"\n")
+ end)
+ end
+
+ -- done with ugly
+
+ if onlyxml then
+
+ os.remove(defaultfilename)
+ os.remove(imagefilename)
+ os.remove(stylefilename)
+ os.remove(templatefilename)
+
+ for i=1,#cssextra do
+ os.remove(joinfile(stylepath,basename(source)))
+ end
+
+ -- os.remove(xmlfilename)
+
+ os.remove(imagefilename)
+ os.remove(stylefilename)
+ os.remove(templatefilename)
+ os.remove(xhtmlfilename)
+ os.remove(specificationfilename)
+ os.remove(htmlfilename)
+
+ result = concat {
+ wholepreamble(true),
+ "<!-- This export file is used for filtering runtime only! -->\n",
+ result,
+ }
+
+ report_export("saving xml data in %a",xmlfilename)
+ io.savedata(xmlfilename,result)
+
+ return
+
+ end
+
local examplefilename = resolvers.find_file("export-example.css")
if examplefilename then
local data = io.loaddata(examplefilename)
@@ -3621,9 +3933,8 @@ local htmltemplate = [[
end
if cssfile then
- local list = table.unique(settings_to_array(cssfile))
- for i=1,#list do
- local source = addsuffix(list[i],"css")
+ for i=1,#cssextra do
+ local source = addsuffix(cssextra[i],"css")
local target = joinfile(stylepath,basename(source))
cssfiles[#cssfiles+1] = source
if not lfs.isfile(source) then
@@ -3638,21 +3949,6 @@ local htmltemplate = [[
local x_styles, h_styles = allusedstylesheets(cssfiles,files,"styles")
- -- at this point we're ready for the content; the collector also does some
- -- housekeeping and data collecting; at this point we still have an xml
- -- representation that uses verbose element names and carries information in
- -- attributes
-
-
- local data = tree.data
- for i=1,#data do
- if data[i].tg ~= "document" then
- data[i] = { }
- end
- end
-
- local result, embedded = allcontent(tree,embedmath) -- embedfile is for testing
-
local attach = backends.nodeinjections.attachfile
if embedfile and attach then
@@ -3666,22 +3962,6 @@ local htmltemplate = [[
mimetype = "application/mathml+xml",
}
end
- -- if embedmath and attach then
- -- local refs = { }
- -- for k, v in sortedhash(embedded) do
- -- attach {
- -- data = v,
- -- file = basename(k),
- -- name = addsuffix(k,"xml"),
- -- registered = k,
- -- reference = k,
- -- title = "xml export snippet: " .. k,
- -- method = v_hidden,
- -- mimetype = "application/mathml+xml",
- -- }
- -- refs[k] = 0
- -- end
- -- end
result = concat {
wholepreamble(true),
@@ -3711,14 +3991,14 @@ local htmltemplate = [[
local xmltree = cleanxhtmltree(xml.convert(result))
--- local xmltree = xml.convert(result)
--- for c in xml.collected(xmltree,"m:mtext[lastindex()=1]/m:mrow") do
--- print(c)
--- end
--- for c in xml.collected(xmltree,"mtext/mrow") do
--- print(c)
--- end
--- local xmltree = cleanxhtmltree(xmltree)
+ -- local xmltree = xml.convert(result)
+ -- for c in xml.collected(xmltree,"m:mtext[lastindex()=1]/m:mrow") do
+ -- print(c)
+ -- end
+ -- for c in xml.collected(xmltree,"mtext/mrow") do
+ -- print(c)
+ -- end
+ -- local xmltree = cleanxhtmltree(xmltree)
xml.save(xmltree,xhtmlfilename)
@@ -3727,8 +4007,8 @@ local htmltemplate = [[
-- looking at identity is somewhat redundant as we also inherit from interaction
-- at the tex end
- local identity = interactions.general.getidentity()
- local metadata = structures.tags.getmetadata()
+ local identity = interactions.general.getidentity()
+ local metadata = structures.tags.getmetadata()
local specification = {
name = usedname,
@@ -3791,19 +4071,15 @@ local htmltemplate = [[
stoptiming(treehash)
end
- local appendaction = nodes.tasks.appendaction
local enableaction = nodes.tasks.enableaction
function structurestags.initializeexport()
if not exporting then
report_export("enabling export to xml")
- -- not yet known in task-ini
- appendaction("shipouts","normalizers", "nodes.handlers.export")
- -- enableaction("shipouts","nodes.handlers.export")
+ enableaction("shipouts","nodes.handlers.export")
enableaction("shipouts","nodes.handlers.accessibility")
enableaction("math", "noads.handlers.tags")
- -- appendaction("finalizers","lists","builders.paragraphs.tag")
- -- enableaction("finalizers","builders.paragraphs.tag")
+ enableaction("everypar","nodes.handlers.checkparcounter")
luatex.registerstopactions(structurestags.finishexport)
exporting = true
end
@@ -3846,6 +4122,7 @@ implement {
{ "svgstyle" },
{ "cssfile" },
{ "file" },
+ { "export" },
}
}
}
@@ -3860,7 +4137,6 @@ implement {
actions = structurestags.initializeexport,
}
-
implement {
name = "settagitemgroup",
actions = structurestags.setitemgroup,
@@ -3880,6 +4156,12 @@ implement {
}
implement {
+ name = "settagformulacontent",
+ actions = structurestags.setformulacontent,
+ arguments = "integer",
+}
+
+implement {
name = "settagdelimitedsymbol",
actions = structurestags.settagdelimitedsymbol,
arguments = "string"
@@ -3962,3 +4244,9 @@ implement {
actions = structurestags.setlist,
arguments = "integer"
}
+
+implement {
+ name = "settagpublication",
+ actions = structurestags.setpublication,
+ arguments = "2 strings"
+}
diff --git a/tex/context/base/mkiv/back-exp.mkiv b/tex/context/base/mkiv/back-exp.mkiv
index ad5ba8371..03dbe709a 100644
--- a/tex/context/base/mkiv/back-exp.mkiv
+++ b/tex/context/base/mkiv/back-exp.mkiv
@@ -17,7 +17,7 @@
%D This is an experimental exporter and a logical follow up on tagging. The
%D exporter assumes a properly tagged document. Some elements get a couple
-%D of attributes becaus eitherwise rendering information would get lost. In
+%D of attributes because otherwise rendering information would get lost. In
%D general we assume that when the \XML\ is converted to \HTML\ some stylesheet
%D is applied anyway.
@@ -241,6 +241,27 @@
\let\specialcontrolspace \explicitcontrolspace
\to \everyenableelements
+\appendtoks
+ \unexpanded\def\dotagregisterformula#1%
+ {\iftrialtypesetting\else
+ \clf_settagformulacontent#1\relax
+ \fi}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagmarginanchor#1%
+ {\iftrialtypesetting\else\clf_settagmarginanchor#1\relax\fi}%
+ \unexpanded\def\dotagmargintext#1%
+ {\iftrialtypesetting\else\clf_settagmargintext#1\relax\fi}%
+\to \everyenableelements
+
+\appendtoks
+ \unexpanded\def\dotagpublication#1#2%
+ {\iftrialtypesetting\else
+ \clf_settagpublication{#1}{#2}\relax
+ \fi}%
+\to \everyenableelements
+
% The action: \setupbackend[export=yes] % or filename
% maybe xhtml css settings will move to setupexport
@@ -261,18 +282,18 @@
\c!author={\directinteractionparameter\c!author},
% \c!firstpage=, % imagename
% \c!lastpage=, % imagename
- \c!alternative=, % html, div
\c!properties=\v!no, % no: ignore, yes: as attribute, otherwise: use as prefix
\c!hyphen=\v!no,
\c!svgstyle=,
\c!cssfile=,
- \c!file={\backendparameter\c!export}] % downward compatibility
+ \c!file=]
\resetsystemmode\v!export
\unexpanded\def\doinitializeexport
{\edef\p_export{\backendparameter\c!export}%
\ifx\p_export\empty \else
+ % yes | xml
\setuptagging[\c!state=\v!start]%
\clf_initializeexport
\setsystemmode\v!export
@@ -300,6 +321,7 @@
svgstyle {\exportparameter\c!svgstyle}%
cssfile {\exportparameter\c!cssfile}%
file {\exportparameter\c!file}%
+ export {\backendparameter\c!export}%
\relax}
\unexpanded\def\dostopexport
diff --git a/tex/context/base/mkiv/back-ini.lua b/tex/context/base/mkiv/back-ini.lua
index fd33d5ddc..b7af1529b 100644
--- a/tex/context/base/mkiv/back-ini.lua
+++ b/tex/context/base/mkiv/back-ini.lua
@@ -6,34 +6,46 @@ if not modules then modules = { } end modules ['back-ini'] = {
license = "see context related readme files"
}
--- -- how to create a shortcut:
---
--- local function something(...)
--- something = backends.codeinjections.something
--- return something(...)
--- end
-
local next, type = next, type
local format = string.format
+local sind, cosd, abs = math.sind, math.cosd, math.abs
+local insert, remove = table.insert, table.remove
+local unpack = unpack
backends = backends or { }
local backends = backends
local trace_backend = false trackers.register("backend.initializers", function(v) trace_finalizers = v end)
+
+local report = logs.reporter("backend")
local report_backend = logs.reporter("backend","initializing")
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
local setaction = nodes.tasks.setaction
-local function nothing() return nil end
+local scanners = tokens.scanners
+local scannumber = scanners.number
+local scankeyword = scanners.keyword
+local scancount = scanners.count
+local scanstring = scanners.string
-backends.nothing = nothing
+local scanners = interfaces.scanners
+
+local implement = interfaces.implement
-local nodeinjections = { }
-local codeinjections = { }
-local registrations = { }
-local tables = allocate()
+local texset = tex.set
+
+local nodeinjections = { }
+local codeinjections = { }
+local registrations = { }
+local tables = allocate()
+
+local function nothing()
+ return nil
+end
+
+backends.nothing = nothing
local function donothing(t,k)
t[k] = nothing
@@ -60,6 +72,17 @@ backends.tables = { } setmetatableindex(backends.tables, tables
backends.current = "unknown"
+local lmtx_mode = nil
+
+local function lmtxmode()
+ if lmtx_mode == nil then
+ lmtx_mode = ((tonumber(CONTEXTLMTXMODE) or 0) > 0) and drivers and drivers.lmtxversion
+ end
+ return lmtx_mode
+end
+
+codeinjections.lmtxmode = lmtxmode
+
function backends.install(what)
if type(what) == "string" then
local backend = backends[what]
@@ -73,7 +96,8 @@ function backends.install(what)
end
backends.current = what
for category, default in next, defaults do
- local target, plugin = backends[category], backend[category]
+ local target = backends[category]
+ local plugin = backend [category]
setmetatableindex(plugin, default)
setmetatableindex(target, plugin)
end
@@ -86,7 +110,13 @@ end
statistics.register("used backend", function()
local bc = backends.current
if bc ~= "unknown" then
- return format("%s (%s)",bc,backends[bc].comment or "no comment")
+ local lmtx = lmtxmode()
+ local cmnt = backends[bc].comment or "no comment"
+ if lmtx then
+ return format("lmtx version %0.2f, %s (%s)",lmtx,bc,cmnt)
+ else
+ return format("%s (%s)",bc,cmnt)
+ end
else
return nil
end
@@ -103,14 +133,6 @@ tables.vfspecials = allocate {
stopslant = comment,
}
--- we'd better have this return something (defaults)
-
-function codeinjections.getpos () return 0, 0 end
-function codeinjections.gethpos () return 0 end
-function codeinjections.getvpos () return 0 end
-function codeinjections.hasmatrix() return false end
-function codeinjections.getmatrix() return 1, 0, 0, 1, 0, 0 end
-
-- can best be here
interfaces.implement {
@@ -139,3 +161,156 @@ backends.included = included
function backends.timestamp()
return os.date("%Y-%m-%dT%X") .. os.timezone(true)
end
+
+-- Also here:
+
+local paper_width = 0
+local paper_height = 0
+
+function codeinjections.setpagedimensions(paperwidth,paperheight)
+ if paperwidth then
+ paper_width = paperwidth
+ end
+ if paperheight then
+ paper_height = paperheight
+ end
+ if not lmtxmode() then
+ texset("global","pageheight",paper_height)
+ texset("global","pagewidth", paper_width)
+ end
+ return paper_width, paper_height
+end
+
+function codeinjections.getpagedimensions()
+ return paper_width, paper_height
+end
+
+implement {
+ name = "shipoutoffset",
+ actions = function()
+ context(lmtxmode() and "0pt" or "-1in") -- the old tex offset
+ end
+}
+
+-- could also be codeinjections
+
+function backends.noflatelua()
+ return status.late_callbacks or 0
+end
+
+--
+
+local stack = { }
+local restore = true -- false
+
+local nodepool = nodes.pool
+local savenode = nodepool.save
+local restorenode = nodepool.restore
+local setmatrixnode = nodepool.setmatrix
+
+updaters.register("backend.update",function()
+ savenode = nodepool.save
+ restorenode = nodepool.restore
+ setmatrixnode = nodepool.setmatrix
+end)
+
+local function stopsomething()
+ local top = remove(stack)
+ if top == false then
+ -- not wrapped
+ elseif top == true then
+ context(restorenode())
+ elseif top then
+ context(setmatrixnode(unpack(top))) -- not really needed anymore
+ context(restorenode())
+ else
+ -- nesting error
+ end
+end
+
+local function startrotation()
+ local a = scannumber()
+ if a == 0 then
+ insert(stack,false)
+ else
+ local s, c = sind(a), cosd(a)
+ if abs(s) < 0.000001 then
+ s = 0 -- otherwise funny -0.00000
+ end
+ if abs(c) < 0.000001 then
+ c = 0 -- otherwise funny -0.00000
+ end
+ context(savenode())
+ context(setmatrixnode(c,s,-s,c))
+ insert(stack,restore and { c, -s, s, c } or true)
+ end
+end
+
+implement { name = "startrotation", actions = startrotation }
+implement { name = "stoprotation", actions = stopsomething }
+
+local function startscaling() -- at the tex end we use sx and sy instead of rx and ry
+ local rx, ry = 1, 1
+ while true do
+ if scankeyword("rx") then
+ rx = scannumber()
+ elseif scankeyword("ry") then
+ ry = scannumber()
+ -- elseif scankeyword("revert") then
+ -- local top = stack[#stack]
+ -- if top then
+ -- rx = top[1]
+ -- ry = top[4]
+ -- else
+ -- rx = 1
+ -- ry = 1
+ -- end
+ else
+ break
+ end
+ end
+ if rx == 1 and ry == 1 then
+ insert(stack,false)
+ else
+ if rx == 0 then
+ rx = 0.0001
+ end
+ if ry == 0 then
+ ry = 0.0001
+ end
+ context(savenode())
+ context(setmatrixnode(rx,0,0,ry))
+ insert(stack,restore and { 1/rx, 0, 0, 1/ry } or true)
+ end
+end
+
+implement { name = "startscaling", actions = startscaling }
+implement { name = "stopscaling", actions = stopsomething }
+
+local function startmatrix() -- rx sx sy ry -- tx, ty
+ local rx, sx, sy, ry = 1, 0, 0, 1
+ while true do
+ if scankeyword("rx") then rx = scannumber()
+ elseif scankeyword("ry") then ry = scannumber()
+ elseif scankeyword("sx") then sx = scannumber()
+ elseif scankeyword("sy") then sy = scannumber()
+ else break end
+ end
+ if rx == 1 and sx == 0 and sy == 0 and ry == 1 then
+ insert(stack,false)
+ else
+ context(savenode())
+ context(setmatrixnode(rx,sx,sy,ry))
+ insert(stack,store and { -rx, -sx, -sy, -ry } or true)
+ end
+end
+
+implement { name = "startmatrix", actions = startmatrix }
+implement { name = "stopmatrix", actions = stopsomething }
+
+local function startmirroring()
+ context(setmatrixnode(-1,0,0,1))
+end
+
+implement { name = "startmirroring", actions = startmirroring }
+implement { name = "stopmirroring", actions = startmirroring } -- not: stopsomething
diff --git a/tex/context/base/mkiv/back-ini.mkiv b/tex/context/base/mkiv/back-ini.mkiv
index e810ecde5..8729403f8 100644
--- a/tex/context/base/mkiv/back-ini.mkiv
+++ b/tex/context/base/mkiv/back-ini.mkiv
@@ -16,10 +16,23 @@
\writestatus{loading}{ConTeXt Backend Macros / Initialization}
+%D The exact page model depends on the backend so we just define some
+%D variables that are used. A helper at the \LUA\ end will synchronize
+%D with the internal variables. We store these in the format.
+
+% \newdimen\backendpageheight
+% \newdimen\backendpagewidth
+% \newdimen\backendinchoffset \backendinchoffset=1in
+
+%D Now we load the \LUA\ code:
+
\registerctxluafile{back-ini}{}
+\registerctxluafile{back-res}{}
-%D We currently have a curious mix between tex and lua backend
-%D handling but eventually most will move to lua.
+\doifelsefileexists{back-out.mkiv}{\loadmarkfile{back-out}}{}
+
+%D We currently have a curious mix between tex and lua backend handling but
+%D eventually most will move to \LUA.
\unprotect
@@ -27,54 +40,84 @@
\ifdefined\everylastbackendshipout \else \newtoks\everylastbackendshipout \fi
\ifdefined\everybackendlastinshipout \else \newtoks\everybackendlastinshipout \fi % e.g. finalize via latelua
-%D Right from the start \CONTEXT\ had a backend system based on
-%D runtime pluggable code. As most backend issues involved specials
-%D and since postprocessors had not that much in common, we ended up
-%D with a system where we could switch backend as well as output code
-%D for multiple backends at the same time.
+%D Right from the start \CONTEXT\ had a backend system based on runtime pluggable
+%D code. As most backend issues involved specials and since postprocessors had not
+%D that much in common, we ended up with a system where we could switch backend as
+%D well as output code for multiple backends at the same time.
%D
-%D Because \LUATEX\ has the backend built in, and since some backend
-%D issues have been moved to the frontend I decided to provide new
-%D backend code for \MKIV, starting with what was actually used.
+%D Because \LUATEX\ has the backend built in, and since some backend issues have
+%D been moved to the frontend I decided to provide new backend code for \MKIV,
+%D starting with what was actually used.
%D
-%D At this moment \DVI\ is no longer used for advanced document
-%D output and we therefore dropped support for this format. Future
-%D versions might support more backends again, but this has a low
-%D priority.
+%D At this moment \DVI\ is no longer used for advanced document output and we
+%D therefore dropped support for this format. Future versions might support more
+%D backends again, but this has a low priority.
%D
-%D Not everything here makes sense and the content of this file will
-%D definitely change (or even go away).
+%D Not everything here makes sense and the content of this file will definitely
+%D change (or even go away).
+
+% rotation
+
+\unexpanded\def\dostartrotation#1%
+ {\forcecolorhack
+ \clf_startrotation#1\relax} % todo: implement without Q q
+
+\unexpanded\def\dostoprotation
+ {\clf_stoprotation
+ \forcecolorhack}
+
+% scaling
+
+\unexpanded\def\dostartscaling#1#2%
+ {\forcecolorhack
+ \clf_startscaling rx #1 ry #2\relax}
-\let \dostartrotation \gobbleoneargument
-\let \dostoprotation \donothing
-\let \dostartscaling \gobbletwoarguments
-\let \dostopscaling \donothing
-\let \dostartmirroring \donothing
-\let \dostopmirroring \donothing
-\let \dotransformnextbox\gobblesixarguments % and pass last box
+\unexpanded\def\dostopscaling
+ {\clf_stopscaling
+ \forcecolorhack}
+
+% mirroring
+
+\unexpanded\def\dostartmirroring
+ {\clf_startmirroring}
+
+\unexpanded\def\dostopmirroring
+ {\clf_stopmirroring}
+
+% transform
+
+\unexpanded\def\dotransformnextbox#1#2#3#4#5#6%
+ {\dowithnextbox{\dodotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\unexpanded\def\dodotransformnextbox#1#2#3#4#5#6%
+ {\hpack
+ {\kern #5\onebasepoint
+ \raise#6\onebasepoint
+ \hpack
+ {\clf_startmatrix rx #1 sx #2 sy #3 ry #4\relax
+ \box\nextbox
+ \clf_stopmatrix}}}
%D \macros
%D {back_ovalbox}
%D
-%D When we look at the implementation, this is a complicated
-%D one. There are seven arguments.
+%D When we look at the implementation, this is a complicated one. There are seven
+%D arguments.
%D
%D \starttyping
%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
-%D to lay over another one (with text). The radius is in
-%D degrees, the stroke and fill are~\type{1} (true) of~\type{0}
-%D (false).
+%D This command has to return a \type {\vbox} which can be used to lay over another
+%D one (with text). The radius is in degrees, the stroke and fill are~\type {1}
+%D (true) of~\type {0} (false).
\let\back_ovalbox \gobbleeightarguments
%D \macros
%D {dostartclipping,dostopclipping}
%D
-%D Clipping is implemented in such a way that an arbitrary code
-%D can be fed.
+%D Clipping is implemented in such a way that an arbitrary code can be fed.
%D
%D \starttyping
%D \dostartclipping {pathname} {width} {height}
@@ -87,9 +130,8 @@
%D \macros
%D {jobsuffix}
%D
-%D By default, \TEX\ produces \DVI\ files which can be
-%D converted to other filetypes. Sometimes it is handy to
-%D know what the target file will be. In other driver
+%D By default, \TEX\ produces \DVI\ files which can be converted to other filetypes.
+%D Sometimes it is handy to know what the target file will be. In other driver
%D modules we wil set \type {\jobsuffix} to \type {pdf}.
%D Backend configuration:
@@ -113,6 +155,12 @@
\clf_setrealspaces{\backendparameter\c!space}%
\to \everysetupbackend
+\appendtoks
+ \ifdefined\clf_resetmapfile
+ \clf_resetmapfile
+ \fi
+\to \everysetupbackend
+
%D For older styles:
\let\setupoutput\gobbleoneoptional
diff --git a/tex/context/base/mkiv/back-pdf.lua b/tex/context/base/mkiv/back-pdf.lua
index f45783e51..8886967e0 100644
--- a/tex/context/base/mkiv/back-pdf.lua
+++ b/tex/context/base/mkiv/back-pdf.lua
@@ -6,302 +6,21 @@ if not modules then modules = { } end modules ['back-pdf'] = {
license = "see context related readme files"
}
--- we could do \pdfmatrix sx <> sy <> etc
+-- We hide the pdf table from users so that we can guarantee no interference with
+-- the way we manage resources, info, etc. Users should use the \type {lpdf}
+-- interface instead. If needed I will provide replacement functionality.
-local sind, cosd = math.sind, math.cosd
-local insert, remove = table.insert, table.remove
-
-local codeinjections = backends.pdf.codeinjections
-
-local context = context
-
-local scanners = tokens.scanners
-local scannumber = scanners.number
-local scankeyword = scanners.keyword
-local scandimen = scanners.dimen
-local scancount = scanners.count
-local scanstring = scanners.string
-
-local scanners = interfaces.scanners
-local implement = interfaces.implement
-
-local report = logs.reporter("backend")
-
-local outputfilename
-
-function codeinjections.getoutputfilename()
- if not outputfilename then
- outputfilename = file.addsuffix(tex.jobname,"pdf")
- end
- return outputfilename
-end
-
-backends.install("pdf")
-
-local f_matrix = string.formatters["%F %F %F %F"] -- 0.8 is default
-
-scanners.pdfrotation = function() -- a
- -- todo: check for 1 and 0 and flush sparse
- local a = scannumber()
- local s, c = sind(a), cosd(a)
- context(f_matrix(c,s,-s,c))
-end
-
--- experimental code (somewhat weird here) .. todo: nodeinjections .. this will only work
--- out well if we also calculate the accumulated cm and wrap inclusions / annotations in
--- the accumulated ... it's a mess
---
--- we could also do the save restore wrapping here + colorhack
-
-local pdfsave = nodes.pool.pdfsave
-local pdfrestore = nodes.pool.pdfrestore
-local pdfsetmatrix = nodes.pool.pdfsetmatrix
-
-local stack = { }
-local restore = true -- false
-
-scanners.pdfstartrotation = function()
- local a = scannumber()
- if a == 0 then
- insert(stack,false)
- else
- local s, c = sind(a), cosd(a)
- context(pdfsave())
- context(pdfsetmatrix(c,s,-s,c))
- insert(stack,restore and { c, -s, s, c } or true)
- end
-end
-
-scanners.pdfstartscaling = function() -- at the tex end we use sx and sy instead of rx and ry
- local rx, ry = 1, 1
- while true do
- if scankeyword("rx") then
- rx = scannumber()
- elseif scankeyword("ry") then
- ry = scannumber()
- -- elseif scankeyword("revert") then
- -- local top = stack[#stack]
- -- if top then
- -- rx = top[1]
- -- ry = top[4]
- -- else
- -- rx = 1
- -- ry = 1
- -- end
- else
- break
- end
- end
- if rx == 1 and ry == 1 then
- insert(stack,false)
- else
- if rx == 0 then
- rx = 0.0001
- end
- if ry == 0 then
- ry = 0.0001
- end
- context(pdfsave())
- context(pdfsetmatrix(rx,0,0,ry))
- insert(stack,restore and { 1/rx, 0, 0, 1/ry } or true)
- end
-end
-
-scanners.pdfstartmatrix = function() -- rx sx sy ry -- tx, ty
- local rx, sx, sy, ry = 1, 0, 0, 1
- while true do
- if scankeyword("rx") then rx = scannumber()
- elseif scankeyword("ry") then ry = scannumber()
- elseif scankeyword("sx") then sx = scannumber()
- elseif scankeyword("sy") then sy = scannumber()
- else break end
- end
- if rx == 1 and sx == 0 and sy == 0 and ry == 1 then
- insert(stack,false)
- else
- context(pdfsave())
- context(pdfsetmatrix(rx,sx,sy,ry))
- insert(stack,store and { -rx, -sx, -sy, -ry } or true)
- end
-end
-
-local function pdfstopsomething()
- local top = remove(stack)
- if top == false then
- -- not wrapped
- elseif top == true then
- context(pdfrestore())
- elseif top then
- context(pdfsetmatrix(unpack(top))) -- not really needed anymore
- context(pdfrestore())
- else
- -- nesting error
- end
-end
-
-scanners.pdfstoprotation = pdfstopsomething
-scanners.pdfstopscaling = pdfstopsomething
-scanners.pdfstopmatrix = pdfstopsomething
-
-scanners.pdfstartmirroring = function()
- context(pdfsetmatrix(-1,0,0,1))
-end
-
-if environment.arguments.nocompression then
- lpdf.setcompression(0,0,true)
-end
-
-scanners.pdfstopmirroring = scanners.pdfstartmirroring
-
--- todo, change the above to implement too --
-
-implement {
- name = "setmapfile",
- arguments = "string",
- actions = pdf.mapfile
-}
-
-implement {
- name = "setmapline",
- arguments = "string",
- actions = pdf.mapline
-}
-
-implement {
+interfaces.implement {
name = "setpdfcompression",
arguments = { "integer", "integer" },
actions = lpdf.setcompression,
}
-local report = logs.reporter("backend","pdftex primitives")
-local trace = false
-
-scanners.pdfannot = function()
- if scankeyword("reserveobjectnum") then
- report("\\pdfannot reserveobjectnum is not (yet) supported")
- -- if trace then
- -- report()
- -- report("\\pdfannot: reserved number (not supported yet)")
- -- report()
- -- end
- else
- local width = false
- local height = false
- local depth = false
- local data = false
- local object = false
- local attr = false
- --
- if scankeyword("useobjnum") then
- object = scancount()
- report("\\pdfannot useobjectnum is not (yet) supported")
- end
- while true do
- if scankeyword("width") then
- width = scandimen()
- elseif scankeyword("height") then
- height = scandimen()
- elseif scankeyword("depth") then
- depth = scandimen()
- else
- break
- end
- end
- if scankeyword("attr") then
- attr = scanstring()
- end
- data = scanstring()
- --
- -- less strict variant:
- --
- -- while true do
- -- if scankeyword("width") then
- -- width = scandimen()
- -- elseif scankeyword("height") then
- -- height = scandimen()
- -- elseif scankeyword("depth") then
- -- depth = scandimen()
- -- elseif scankeyword("useobjnum") then
- -- object = scancount()
- -- elseif scankeyword("attr") then
- -- attr = scanstring()
- -- else
- -- data = scanstring()
- -- break
- -- end
- -- end
- --
- -- if trace then
- -- report()
- -- report("\\pdfannot:")
- -- report()
- -- report(" object: %s",object or "<unset> (not supported yet)")
- -- report(" width : %p",width or "<unset>")
- -- report(" height: %p",height or "<unset>")
- -- report(" depth : %p",depth or "<unset>")
- -- report(" attr : %s",attr or "<unset>")
- -- report(" data : %s",data or "<unset>")
- -- report()
- -- end
- context(backends.nodeinjections.annotation(width or 0,height or 0,depth or 0,data or ""))
- end
+if CONTEXTLMTXMODE == 0 then
+ updaters.apply("backend.update.pdf")
+ updaters.apply("backend.update.lpdf")
+ updaters.apply("backend.update.tex")
+ updaters.apply("backend.update")
end
-scanners.pdfdest = function()
- local name = false
- local zoom = false
- local view = false
- local width = false
- local height = false
- local depth = false
- if scankeyword("num") then
- report("\\pdfdest num is not (yet) supported")
- elseif scankeyword("name") then
- name = scanstring()
- end
- if scankeyword("xyz") then
- view = "xyz"
- if scankeyword("zoom") then
- report("\\pdfdest zoom is ignored")
- zoom = scancount() -- will be divided by 1000 in the backend
- end
- elseif scankeyword("fitbh") then
- view = "fitbh"
- elseif scankeyword("fitbv") then
- view = "fitbv"
- elseif scankeyword("fitb") then
- view = "fitb"
- elseif scankeyword("fith") then
- view = "fith"
- elseif scankeyword("fitv") then
- view = "fitv"
- elseif scankeyword("fitr") then
- view = "fitr"
- while true do
- if scankeyword("width") then
- width = scandimen()
- elseif scankeyword("height") then
- height = scandimen()
- elseif scankeyword("depth") then
- depth = scandimen()
- else
- break
- end
- end
- elseif scankeyword("fit") then
- view = "fit"
- end
- -- if trace then
- -- report()
- -- report("\\pdfdest:")
- -- report()
- -- report(" name : %s",name or "<unset>")
- -- report(" view : %s",view or "<unset>")
- -- report(" zoom : %s",zoom or "<unset> (not supported)")
- -- report(" width : %p",width or "<unset>")
- -- report(" height: %p",height or "<unset>")
- -- report(" depth : %p",depth or "<unset>")
- -- report()
- -- end
- context(backends.nodeinjections.destination(width or 0,height or 0,depth or 0,{ name or "" },view or "fit"))
-end
+backends.install("pdf")
diff --git a/tex/context/base/mkiv/back-pdf.mkiv b/tex/context/base/mkiv/back-pdf.mkiv
index 3b0dd7852..9e88ab193 100644
--- a/tex/context/base/mkiv/back-pdf.mkiv
+++ b/tex/context/base/mkiv/back-pdf.mkiv
@@ -11,11 +11,10 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D The less ther ei shere, the better.
+%D The less there is here, the better.
\writestatus{loading}{ConTeXt Backend Macros / PDF}
-%registerctxluafile{lpdf-aux}{optimize} % common helpers
\registerctxluafile{lpdf-ini}{optimize}
\registerctxluafile{lpdf-nod}{}
\registerctxluafile{lpdf-col}{}
@@ -32,9 +31,22 @@
\registerctxluafile{lpdf-swf}{} % this will become a module
\registerctxluafile{lpdf-tag}{}
\registerctxluafile{lpdf-fmt}{}
-\registerctxluafile{lpdf-epd}{}
+\registerctxluafile{lpdf-pde}{}
+
+\ifcase\contextlmtxmode\else
+ \registerctxluafile{lpdf-img}{optimize}
+\fi
+
\registerctxluafile{lpdf-epa}{}
+\ifcase\contextlmtxmode\else
+ \registerctxluafile{lpdf-emb}{optimize}
+\fi
+
+\registerctxluafile{back-pdp}{}
+
+\registerctxluafile{lpdf-fnt}{}
+
\registerctxluafile{back-pdf}{} % some code will move to lpdf-*
\loadmarkfile{back-u3d} % this will become a module
@@ -47,26 +59,53 @@
%D
%D Here we initialize some internal quantities. We also protect them.
-\outputmode\plusone \let\outputmode\relax \newcount\outputmode \outputmode\plusone
+\ifdefined\outputmode
+ \outputmode\plusone
+ \let\outputmode\relax
+ \newcount\outputmode
+ \outputmode\plusone
+ \let\normaloutputmode\outputmode
+\fi
%D Because we do a lot in \LUA\ and don't want interferences, we nil most of the
%D \PDFTEX\ primitives. Of course one can always use the \type {\pdfvariable},
%D \type {\pdfextension} and \type {\pdffeedback} primitives but it will probably
%D have bad side effects.
+%D For the moment we put these here as they are pdf related but they might move to
+%D a better place. We overload the primitives with our own but use a bit of indirection
+%D for the purpose of tracing.
+
+\unexpanded\def\saveboxresource {\clf_saveboxresource}
+\unexpanded\def\lastsavedboxresourceindex {\numexpr\clf_lastsavedboxresourceindex\relax}
+\unexpanded\def\useboxresource {\clf_useboxresource}
+
+\unexpanded\def\saveimageresource {\clf_saveimageresource}
+\unexpanded\def\lastsavedimageresourceindex{\numexpr\clf_lastsavedimageresourceindex\relax}
+\unexpanded\def\lastsavedimageresourcepages{\numexpr\clf_lastsavedimageresourcepages\relax}
+\unexpanded\def\useimageresource {\clf_useimageresource}
+
+\unexpanded\def\savepos {\clf_savepos}
+ \def\lastxpos {\clf_lastxpos}
+ \def\lastypos {\clf_lastypos}
+
+\unexpanded\def\pdfextension {\clf_pdfextension}
+ \def\pdffeedback {\clf_pdffeedback}
+
%D These are no-ops and don't even intercept what comes next. Maybe some day
%D I'll write a parser that maps onto \CONTEXT.
\unexpanded\def\unsupportedpdfprimitive#1%
- {\writestatus{error}{the primitive \string#1\space is not supported}}
+ {\writestatus{fatal error}{the primitive \string#1\space is not supported}%
+ \directlua{os.exit()}}
\unexpanded\def\pdfcolorstack {\unsupportedpdfprimitive\pdfcolorstack}
\unexpanded\def\pdfcolorstackinit{\unsupportedpdfprimitive\pdfcolorstackinit}
-%unexpanded\def\pdfannot {\unsupportedpdfprimitive\pdfannot}
+% pdfannot
\unexpanded\def\pdfstartlink {\unsupportedpdfprimitive\pdfstartlink}
\unexpanded\def\pdfendlink {\unsupportedpdfprimitive\pdfendlink}
\unexpanded\def\pdfoutline {\unsupportedpdfprimitive\pdfoutline}
-%unexpanded\def\pdfdest {\unsupportedpdfprimitive\pdfdest}
+% pdfdest
\unexpanded\def\pdfthread {\unsupportedpdfprimitive\pdfthread}
\unexpanded\def\pdfstartthread {\unsupportedpdfprimitive\pdfstartthread}
\unexpanded\def\pdfendthread {\unsupportedpdfprimitive\pdfendthread}
@@ -97,23 +136,24 @@
%D But we still provide:
-\unexpanded\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount}
-\unexpanded\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine }
-\unexpanded\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree}
+\unexpanded\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount}
+\unexpanded\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree}
+\unexpanded\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine }
+\unexpanded\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree}
%D These might even become no-ops as we don't need them in \CONTEXT:
-\unexpanded\def\pdfmapfile#1{\clf_setmapfile{#1}}
-\unexpanded\def\pdfmapline#1{\clf_setmapline{#1}}
+\unexpanded\def\pdfmapfile#1{} % obsolete
+\unexpanded\def\pdfmapline#1{} % obsolete
%D We don't support these directives, at least not this way. If they are needed
%D by third party modules we can provide some interface.
-% \pdfcreationdate
+%pdfcreationdate
\let\pdfdecimaldigits \relax \newcount\pdfdecimaldigits
\let\pdfdestmargin \relax \newdimen\pdfdestmargin
-% \pdffontname
-% \pdffontobjnum
+% pdffontname
+% pdffontobjnum
\let\pdffontsize \relax \newcount\pdffontsize
\let\pdfgamma \relax \newcount\pdfgamma
\let\pdfgentounicode \relax \newcount\pdfgentounicode
@@ -128,21 +168,21 @@
\let\pdfinclusioncopyfonts \relax \newcount\pdfinclusioncopyfonts
\let\pdfinclusionerrorlevel \relax \newcount\pdfinclusionerrorlevel
\let\pdfinfoomitdate \relax \newcount\pdfinfoomitdate
-% \pdflastannot
-% \pdflastlink
+% pdflastannot
+% pdflastlink
\let\pdflinkmargin \relax \newdimen\pdflinkmargin
\let\pdfmajorversion \relax \newcount\pdfmajorversion
\let\pdfminorversion \relax \newcount\pdfminorversion
\let\pdfpagebox \relax \newcount\pdfpagebox
-% \pdfpageref
+% pdfpageref
\let\pdfpkfixeddpi \relax \newcount\pdfpkfixeddpi
\let\pdfpkmode \relax \newtoks \pdfpkmode
\let\pdfpkresolution \relax \newcount\pdfpkresolution
-% \pdfretval
+% pdfretval
\let\pdfsuppressoptionalinfo \relax \newcount\pdfsuppressoptionalinfo
\let\pdfsuppressptexinfo \relax \newcount\pdfsuppressptexinfo
-% \pdftexrevision
-% \pdftexversion
+% pdftexrevision
+% pdftexversion
\let\pdfthreadmargin \relax \newdimen\pdfthreadmargin
\let\pdftrailerid \relax \newtoks \pdftrailerid
\let\pdfuniqueresname \relax \newcount\pdfuniqueresname
@@ -152,27 +192,33 @@
%D These are still accepted but are normally not needed.
+\let\pdfxform \saveboxresource
+\let\pdfximage \saveimageresource
+
\let\pdflastxform \lastsavedboxresourceindex
\let\pdflastximage \lastsavedimageresourceindex
-\let\pdflastximagepages \lastsavedimageresourcepages
-\let\pdflastxpos \lastxpos
-\let\pdflastypos \lastypos
+
\let\pdfrefxform \useboxresource
\let\pdfrefximage \useimageresource
+
+\let\pdflastximagepages \lastsavedimageresourcepages
+
\let\pdfsavepos \savepos
-\let\pdfxform \saveboxresource
-\let\pdfximage \saveimageresource
+\let\pdflastxpos \lastxpos
+\let\pdflastypos \lastypos
%D For the moment we keep these as they are but they will become \LUA\ calls
%D eventually, after which we will nil the three \type {\pdf} interface primitives.
-\normalprotected\def\pdfliteral {\pdfextension literal }
-\normalprotected\def\pdfobj {\pdfextension obj }
- \def\pdflastobj {\numexpr\pdffeedback lastobj\relax}
+\normalprotected\def\pdfliteral {\clf_pdfliteral}%
+
+\normalprotected\def\pdfobj {\clf_pdfobj}%
+\normalprotected\def\pdflastobj {\numexpr\clf_pdflastobj\relax}%
+
\normalprotected\def\pdfrefobj {\pdfextension refobj }
-\normalprotected\def\pdfrestore {\pdfextension restore\relax}
-\normalprotected\def\pdfsave {\pdfextension save\relax}
-\normalprotected\def\pdfsetmatrix{\pdfextension setmatrix }
+\normalprotected\def\pdfrestore {\clf_restore}
+\normalprotected\def\pdfsave {\clf_save}
+\normalprotected\def\pdfsetmatrix{\clf_setmatrix}
%D This one can be consulted by users although the suffix is also a system mode.
@@ -225,84 +271,6 @@
\def\pdfcolor #1{\clf_lpdf_color\numexpr\thecolorattribute{#1}\relax}
\let\PDFcolor\pdfcolor
-%D Transformations
-
-% rotation
-
-\unexpanded\def\dostartrotation#1%
- {\forcecolorhack
- \clf_pdfstartrotation#1\relax} % todo: implement without Q q
-
-\unexpanded\def\dostoprotation
- {\clf_pdfstoprotation
- \forcecolorhack}
-
-% scaling
-
-\unexpanded\def\dostartscaling#1#2%
- {\forcecolorhack
- \clf_pdfstartscaling rx #1 ry #2\relax}
-
-\unexpanded\def\dostopscaling
- {\clf_pdfstopscaling
- \forcecolorhack}
-
-% mirroring
-
-\unexpanded\def\dostartmirroring
- {\clf_pdfstartmirroring}
-
-\unexpanded\def\dostopmirroring
- {\clf_pdfstopmirroring}
-
-% transform
-
-\unexpanded\def\dotransformnextbox#1#2#3#4#5#6%
- {\dowithnextbox{\dodotransformnextbox{#1}{#2}{#3}{#4}{#5}{#6}}}
-
-\unexpanded\def\dodotransformnextbox#1#2#3#4#5#6%
- {\hpack
- {\kern #5\onebasepoint
- \raise#6\onebasepoint
- \hpack
- {\clf_pdfstartmatrix rx #1 sx #2 sy #3 ry #4\relax
- \box\nextbox
- \clf_pdfstopmatrix}}}
-
-% somehow the shift is not happening .. bug in luatex?
-%
-% \unexpanded\def\dodotransformnextbox#1#2#3#4#5#6%
-% {\ctxcommand{pdftransformbox(\number\nextbox,#1,#2,#3,#4,\number\dimexpr#5\onebasepoint,\number\dimexpr#6\onebasepoint)}%
-% \box\nextbox}
-%
-% \startluacode
-% function commands.pdftransformbox(box,rx,sx,sy,ry,tx,ty)
-% if rx == 1 and sx == 0 and sy == 0 and ry == 1 then
-% if tx == 0 and ty == 0 then
-% local b = nodes.hpack(nodes.concat {
-% nodes.pool.kern(tx),
-% nodes.takebox(box),
-% })
-% b.shift = -ty
-% tex.setbox(box,b)
-% else
-% -- no need to transform
-% end
-% else
-% local b = nodes.hpack(nodes.concat {
-% nodes.pool.kern(tx),
-% nodes.pool.pdfsave(),
-% nodes.pool.pdfsetmatrix(rx,sx,sy,ry),
-% nodes.takebox(box),
-% nodes.pool.pdfsetmatrix(-rx,-sx,-sy,-ry),
-% nodes.pool.pdfrestore(),
-% })
-% b.shift = -ty
-% tex.setbox(box,b)
-% end
-% end
-% \stopluacode
-
% clipping
\unexpanded\def\dostartclipping#1#2#3% we can move this to lua and only set a box here
diff --git a/tex/context/base/mkiv/back-pdp.lua b/tex/context/base/mkiv/back-pdp.lua
new file mode 100644
index 000000000..7363cfcae
--- /dev/null
+++ b/tex/context/base/mkiv/back-pdp.lua
@@ -0,0 +1,453 @@
+if not modules then modules = { } end modules ['back-pdp'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is temporary ... awaiting a better test .. basically we can
+-- always use this: pdf primitives.
+
+local context = context
+
+local lpdfreserveobject = lpdf.reserveobject
+local lpdfcompresslevel = lpdf.compresslevel
+local lpdfobj = lpdf.obj
+local lpdfpagereference = lpdf.pagereference
+local lpdfxformname = lpdf.xformname
+
+local jobpositions = job.positions
+local gethpos = jobpositions.gethpos
+local getvpos = jobpositions.getvpos
+
+local tokenscanners = tokens.scanners
+local scanword = tokenscanners.word
+local scankeyword = tokenscanners.keyword
+local scanstring = tokenscanners.string
+local scaninteger = tokenscanners.integer
+local scandimension = tokenscanners.dimension
+
+local trace = false trackers.register("commands", function(v) trace = v end)
+local report = logs.reporter("command")
+
+local nodepool = nodes.pool
+local newsavepos = nodepool.savepos
+local newliteral = nodepool.literal
+local newsave = nodepool.save
+local newrestore = nodepool.restore
+local newsetmatrix = nodepool.setmatrix
+
+local implement = interfaces.implement
+local constants = interfaces.constants
+local variables = interfaces.variables
+
+-- helper
+
+local function scanwhd()
+ local width, height, depth
+ while true do
+ if scankeyword("width") then
+ width = scandimension()
+ elseif scankeyword("height") then
+ height = scandimension()
+ elseif scankeyword("depth") then
+ depth = scandimension()
+ else
+ break
+ end
+ end
+ if width or height or depth then
+ return width or 0, height or 0, depth or 0
+ else
+ -- we inherit
+ end
+end
+
+-- positions
+
+local function savepos()
+ context(newsavepos())
+end
+
+local function lastxpos()
+ context(gethpos())
+end
+
+local function lastypos()
+ context(getvpos())
+end
+
+implement { name = "savepos", actions = savepos }
+implement { name = "lastxpos", actions = lastxpos }
+implement { name = "lastypos", actions = lastypos }
+
+-- literals
+
+local function pdfliteral()
+ context(newliteral(scanword() or "origin",scanstring()))
+end
+
+implement { name = "pdfliteral", actions = pdfliteral }
+
+-- box resources
+
+local boxresources = tex.boxresources
+local savebox = boxresources.save
+local usebox = boxresources.use
+
+local lastindex = 0
+
+local function saveboxresource()
+ local immediate = true
+ local kind = scankeyword("type") and scaninteger() or 0
+ local attributes = scankeyword("attr") and scanstring() or nil
+ local resources = scankeyword("resources") and scanstring() or nil
+ local margin = scankeyword("margin") and scandimension() or 0 -- register
+ local boxnumber = scaninteger()
+ --
+ lastindex = savebox(boxnumber,attributes,resources,immediate,kind,margin)
+ if trace then
+ report("\\saveboxresource: index %i",lastindex)
+ end
+end
+
+local function lastsavedboxresourceindex()
+ if trace then
+ report("\\lastsaveboxresource: index %i",lastindex)
+ end
+ context("%i",lastindex)
+end
+
+local function useboxresource()
+ local width, height, depth = scanwhd()
+ local index = scaninteger()
+ local node = usebox(index,width,height,depth)
+ if trace then
+ report("\\useboxresource: index %i",index)
+ end
+ context(node)
+end
+
+implement { name = "saveboxresource", actions = saveboxresource }
+implement { name = "lastsavedboxresourceindex", actions = lastsavedboxresourceindex }
+implement { name = "useboxresource", actions = useboxresource }
+
+-- image resources (messy: will move)
+
+local imageresources = { }
+local lastindex = 0
+local lastpages = 1
+
+local function saveimageresource()
+ local width, height, depth = scanwhd()
+ local page = 1
+ local immediate = true
+ local margin = 0 -- or dimension
+ local attributes = scankeyword("attr") and scanstring() or nil
+ if scankeyword("named") then
+ scanstring() -- ignored
+ elseif scankeyword("page") then
+ page = scaninteger()
+ end
+ local userpassword = scankeyword("userpassword") and scanstring() or nil
+ local ownerpassword = scankeyword("ownerpassword") and scanstring() or nil
+ local visiblefilename = scankeyword("visiblefilename") and scanstring() or nil
+ local colorspace = scankeyword("colorspace") and scaninteger() or nil
+ local pagebox = scanword() or nil
+ local filename = scanstring()
+-- pcall
+ context.getfiguredimensions( { filename }, {
+ [constants.userpassword] = userpassword,
+ [constants.ownerpassword] = ownerpassword,
+ [constants.page] = page or 1,
+ [constants.size] = pagebox,
+ })
+ context.relax()
+ lastindex = lastindex + 1
+ lastpages = 1
+ imageresources[lastindex] = {
+ filename = filename,
+ page = page or 1,
+ size = pagebox,
+ width = width,
+ height = height,
+ depth = depth,
+ attr = attributes,
+ -- margin = margin,
+ }
+end
+
+local function lastsavedimageresourceindex()
+ context("%i",lastindex or 0)
+end
+
+local function lastsavedimageresourcepages()
+ context("%i",lastpages or 0) -- todo
+end
+
+local function useimageresource()
+ local width, height, depth = scanwhd()
+ if scankeyword("keepopen") then
+ -- ignored
+ end
+ local index = scaninteger()
+ local l = imageresources[index]
+ if l then
+ if not (width or height or depth) then
+ width = l.width
+ height = l.height
+ depth = l.depth
+ end
+-- pcall
+ context.externalfigure( { l.filename }, {
+ [constants.userpassword] = l.userpassword,
+ [constants.ownerpassword] = l.ownerpassword,
+ [constants.width] = width and (width .. "sp") or nil,
+ [constants.height] = height and (height .. "sp") or nil,
+ [constants.page] = l.page or 1,
+ [constants.size] = pagebox,
+ })
+ context.relax()
+ else
+ print("no image resource",index)
+ end
+end
+
+implement { name = "saveimageresource", actions = saveimageresource }
+implement { name = "lastsavedimageresourceindex", actions = lastsavedimageresourceindex }
+implement { name = "lastsavedimageresourcepages", actions = lastsavedimageresourcepages }
+implement { name = "useimageresource", actions = useimageresource }
+
+-- objects
+
+local lastobjnum = 0
+
+local function pdfobj()
+ if scankeyword("reserveobjnum") then
+ lastobjnum = lpdfreserveobject()
+ if trace then
+ report("\\pdfobj reserveobjnum: object %i",lastobjnum)
+ end
+ else
+ local immediate = true
+ local objnum = scankeyword("useobjnum") and scaninteger() or lpdfreserveobject()
+ local uncompress = scankeyword("uncompressed") or lpdfcompresslevel() == 0
+ local streamobject = scankeyword("stream") and true or false
+ local attributes = scankeyword("attr") and scanstring()
+ local fileobject = scankeyword("file")
+ local content = scanstring()
+ local object = {
+ immediate = immediate,
+ attr = attributes,
+ objnum = objnum,
+ type = streamobject and "stream" or nil,
+ compresslevel = uncompress and 0 or nil,
+ }
+ if fileobject then
+ object.filename = content
+ else
+ object.string = content
+ end
+ lpdfobj(object)
+ lastobjnum = objnum
+ if trace then
+ report("\\pdfobj: object %i",lastobjnum)
+ end
+ end
+end
+
+local function pdflastobj()
+ context("%i",lastobjnum)
+ if trace then
+ report("\\lastobj: object %i",lastobjnum)
+ end
+end
+
+local function pdfrefobj()
+ local objnum = scaninteger()
+ if trace then
+ report("\\refobj: object %i (todo)",objnum)
+ end
+end
+
+implement { name = "pdfobj", actions = pdfobj }
+implement { name = "pdflastobj", actions = pdflastobj }
+implement { name = "pdfrefobj", actions = pdfrefobj }
+
+-- annotations
+
+local lastobjnum = 0
+
+local function pdfannot()
+ if scankeyword("reserveobjnum") then
+ lastobjnum = lpdfreserveobject()
+ if trace then
+ report("\\pdfannot reserveobjnum: object %i",lastobjnum)
+ end
+ else
+ local width = false
+ local height = false
+ local depth = false
+ local data = false
+ local object = false
+ local attr = false
+ --
+ if scankeyword("useobjnum") then
+ object = scancount()
+ report("\\pdfannot useobjectnum is not (yet) supported")
+ end
+ local width, height, depth = scanwhd()
+ if scankeyword("attr") then
+ attr = scanstring()
+ end
+ data = scanstring()
+ context(backends.nodeinjections.annotation(width or 0,height or 0,depth or 0,data or ""))
+ end
+end
+
+implement { name = "pdfannot", actions = pdfannot }
+
+local function pdfdest()
+ local name = false
+ local zoom = false
+ local view = false
+ local width = false
+ local height = false
+ local depth = false
+ if scankeyword("num") then
+ report("\\pdfdest num is not (yet) supported")
+ elseif scankeyword("name") then
+ name = scanstring()
+ end
+ if scankeyword("xyz") then
+ view = "xyz"
+ if scankeyword("zoom") then
+ report("\\pdfdest zoom is ignored")
+ zoom = scancount() -- will be divided by 1000 in the backend
+ end
+ elseif scankeyword("fitbh") then
+ view = "fitbh"
+ elseif scankeyword("fitbv") then
+ view = "fitbv"
+ elseif scankeyword("fitb") then
+ view = "fitb"
+ elseif scankeyword("fith") then
+ view = "fith"
+ elseif scankeyword("fitv") then
+ view = "fitv"
+ elseif scankeyword("fitr") then
+ view = "fitr"
+ width, height, depth = scanwhd()
+ elseif scankeyword("fit") then
+ view = "fit"
+ end
+ context(backends.nodeinjections.destination(width or 0,height or 0,depth or 0,{ name or "" },view or "fit"))
+end
+
+implement { name = "pdfdest", actions = pdfdest }
+
+-- management
+
+
+local function pdfsave()
+ context(newsave())
+end
+
+local function pdfrestore()
+ context(newrestore())
+end
+
+local function pdfsetmatrix()
+ context(newsetmatrix(scanstring()))
+end
+
+
+-- extras
+
+local function pdfpageref()
+ context(lpdfpagereference())
+end
+
+local function pdfxformname()
+ context(lpdfxformname())
+end
+
+-- extensions: literal dest annot save restore setmatrix obj refobj colorstack
+-- startlink endlink startthread endthread thread outline glyphtounicode fontattr
+-- mapfile mapline includechars catalog info names trailer
+
+local extensions = {
+ literal = pdfliteral,
+ obj = pdfobj,
+ refobj = pdfrefobj,
+ dest = pdfdest,
+ annot = pdfannot,
+ save = pdfsave,
+ restore = pdfrestore,
+ setmatrix = pdfsetmatrix,
+}
+
+local function pdfextension()
+ local w = scanword()
+ if w then
+ local e = extensions[w]
+ if e then
+ e()
+ else
+ report("\\pdfextension: unknown %a",w)
+ end
+ end
+end
+
+implement { name = "pdfextension", actions = pdfextension }
+
+-- feedbacks: colorstackinit creationdate fontname fontobjnum fontsize lastannot
+-- lastlink lastobj pageref retval revision version xformname
+
+local feedbacks = {
+ lastobj = pdflastobj,
+ pageref = pdfpageref,
+ xformname = pdfxformname,
+}
+
+local function pdffeedback()
+ local w = scanword()
+ if w then
+ local f = feedbacks[w]
+ if f then
+ f()
+ else
+ report("\\pdffeedback: unknown %a",w)
+ end
+ end
+end
+
+implement { name = "pdffeedback", actions = pdffeedback }
+
+-- variables: (integers:) compresslevel decimaldigits gamma gentounicode
+-- ignoreunknownimages imageaddfilename imageapplygamma imagegamma imagehicolor
+-- imageresolution inclusioncopyfonts inclusionerrorlevel majorversion minorversion
+-- objcompresslevel omitcharset omitcidset pagebox pkfixeddpi pkresolution
+-- recompress suppressoptionalinfo uniqueresname (dimensions:) destmargin horigin
+-- linkmargin threadmargin vorigin xformmargin (tokenlists:) pageattr pageresources
+-- pagesattr pkmode trailerid xformattr xformresources
+
+-- local variables = {
+-- }
+--
+-- local function pdfvariable()
+-- local w = scanword()
+-- if w then
+-- local f = variables[w]
+-- if f then
+-- f()
+-- else
+-- print("invalid variable",w)
+-- end
+-- else
+-- print("missing variable")
+-- end
+-- end
+
+--------- { name = "pdfvariable", actions = pdfvariable }
diff --git a/tex/context/base/mkiv/back-res.lua b/tex/context/base/mkiv/back-res.lua
new file mode 100644
index 000000000..be92c74a6
--- /dev/null
+++ b/tex/context/base/mkiv/back-res.lua
@@ -0,0 +1,44 @@
+if not modules then modules = { } end modules ['back-res'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- A box resource has an index. This happens to be an object number
+-- due to the pdf backend but in fact it's an abstraction. This is why
+-- we have explicit fetchers. The internal number (as in \Fm123) is yet
+-- another number.
+
+local tex_saveboxresource = tex.saveboxresource
+local tex_useboxresource = tex.useboxresource
+local tex_getboxresourcebox = tex.getboxresourcebox
+local tex_getboxresourcedimensions = tex.getboxresourcedimensions
+
+updaters.register("backend.update",function()
+ tex_saveboxresource = tex.saveboxresource
+ tex_useboxresource = tex.useboxresource
+ tex_getboxresourcebox = tex.getboxresourcebox
+ tex_getboxresourcedimensions = tex.getboxresourcedimensions
+end)
+
+tex.boxresources = {
+ save = function(...) return tex_saveboxresource(...) end,
+ use = function(...) return tex_useboxresource(...) end,
+ getbox = function(...) return tex_getboxresourcebox(...) end,
+ getdimensions = function(...) return tex_getboxresourcedimensions(...) end,
+}
+
+-- local tex_saveimageresource = tex.saveimageresource
+-- local tex_useimageresource = tex.useimageresource
+--
+-- updaters.register("backend.update",function()
+-- tex_saveimageresource = tex.saveimageresource
+-- tex_useimageresource = tex.useimageresource
+-- end)
+--
+-- tex.imageresources = {
+-- save = function(...) return tex_saveimageresource(...) end,
+-- use = function(...) return tex_useimageresource(...) end,
+-- }
diff --git a/tex/context/base/mkiv/back-swf.mkiv b/tex/context/base/mkiv/back-swf.mkiv
index 0a53a8fd2..20a94266a 100644
--- a/tex/context/base/mkiv/back-swf.mkiv
+++ b/tex/context/base/mkiv/back-swf.mkiv
@@ -11,6 +11,9 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+%D The question is: should I still document this in interaction.tex or just
+%D assume it's obsolete technology \unknown
+
%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
@@ -58,6 +61,8 @@
%D [file=test.mp4,
%D label=foo]
%D
+%D \useJSscripts[vplayer] % or \useJSscripts[videoplayer]
+%D
%D \goto{START} [JS(StartShockwave{foo})]
%D \goto{REWIND}[JS(RewindShockwave{foo})]
%D \goto{PAUSE} [JS(PauseShockwave{foo})]
@@ -84,100 +89,8 @@
\unprotect
-\startluaparameterset[shockwave:display]
- toolbar = true,
- -- preview = "somefile",
- open = "click",
- close = "focus",
-\stopluaparameterset
-
-% using vplayer9.swf from ctan:
-
-\useexternalfigure
- [shockwave]
- [vplayer9.swf]
-% [arguments=\luaparameterset{shockwave:arguments}{src="\externalfigureparameter\v!file",source="\externalfigureparameter\v!file"},
- [\c!arguments=\luaparameterset{shockwave:arguments}{source="\externalfigureparameter\v!file",autoPlay=true},
- \c!resources=\luaparameterset{shockwave:resources}{files={"\externalfigureparameter\v!file"}},
- \c!display=shockwave:display]
-
-\startJSpreamble shockwave used now
- function StartShockwave(label) {
- var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
- if (rm.activated) {
- // ok
- } else {
- rm.activated = true ;
- }
- rm.callAS("rewind") ;
- rm.callAS("playPause") ;
- }
- function StopShockwave(label) {
- var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
- if (rm.activated) {
- rm.callAS("pause") ;
- rm.callAS("rewind") ;
- }
- }
- function RewindShockwave(label) {
- var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
- if (rm.activated) {
- rm.callAS("rewind") ;
- }
- }
- function PauseShockwave(label) {
- var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
- if (rm.activated) {
- rm.callAS("playPause") ;
- }
- }
-\stopJSpreamble
-
-% using videoplayer.swf from adobe or strobemediaplayback.swf from sourceforge:
-
-%\useexternalfigure
-% [shockwave]
-% [videoplayer.swf]
-% [\c!arguments=\luaparameterset{shockwave:arguments}{source="\externalfigureparameter\v!file"},
-% \c!resources=\luaparameterset{shockwave:resources}{files={"\externalfigureparameter\v!file"}},
-% \c!display=shockwave:display]
-
-\startJSpreamble shockwave used now
- function StartShockwave(label) {
- var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
- if (rm.activated) {
- rm.callAS("multimedia_play") ;
- } else {
- rm.activated = true ;
- }
- }
- function StopShockwave(label) {
- var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
- if (rm.activated) {
- rm.callAS("multimedia_pause") ;
- rm.callAS("multimedia_rewind") ;
- }
- }
- function RewindShockwave(label) {
- var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
- if (rm.activated) {
- rm.callAS("multimedia_rewind") ;
- }
- }
- function PauseShockwave(label) {
- var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
- if (rm.activated) {
- rm.callAS("multimedia_pause") ;
- }
- }
-\stopJSpreamble
-
-% \useexternalfigure
-% [shockwave]
-% [strobemediaplayback.swf]
-% [arguments=\luaparameterset{shockwave:arguments}{src="\externalfigureparameter\v!file"},
-% resources=\luaparameterset{shockwave:resources}{files={"\externalfigureparameter\v!file"}},
-% display=shockwave:display]
+%D The code has moved to the (explicitly loaded) \JAVASCRIPT\ modules. See there
+%D for more info.
\protect \endinput
diff --git a/tex/context/base/mkiv/bibl-bib.mkiv b/tex/context/base/mkiv/bibl-bib.mkiv
index 784c87a02..60291ee71 100644
--- a/tex/context/base/mkiv/bibl-bib.mkiv
+++ b/tex/context/base/mkiv/bibl-bib.mkiv
@@ -812,12 +812,12 @@
{\iflocation
\edef\temp{\bibtexcitationparameter\c!interaction}%
\ifx\temp\v!stop
- \@EA@EA@EA\secondoftwoarguments
+ \doubleexpandafter\secondoftwoarguments
\else
- \@EA@EA@EA\firstoftwoarguments
+ \doubleexpandafter\firstoftwoarguments
\fi
\else
- \@EA\secondoftwoarguments
+ \expandafter\secondoftwoarguments
\fi}
\let\doifbibtexinteractionelse\doifelsebibtexinteraction
diff --git a/tex/context/base/mkiv/bibl-tra.mkiv b/tex/context/base/mkiv/bibl-tra.mkiv
index 3ff07ead5..5389400f3 100644
--- a/tex/context/base/mkiv/bibl-tra.mkiv
+++ b/tex/context/base/mkiv/bibl-tra.mkiv
@@ -1500,7 +1500,7 @@
\c!numbercommand=\bibleftnumber]
\unexpanded\def\preloadbiblist
- {\globallet\preloadbiblist\relax
+ {\glet\preloadbiblist\relax
\dousepublications\jobname}
% \appendtoks \preloadbiblist \to \everysetuppublications
diff --git a/tex/context/base/mkiv/buff-imp-default.mkiv b/tex/context/base/mkiv/buff-imp-default.mkiv
index a4ad788bb..4da4ff0df 100644
--- a/tex/context/base/mkiv/buff-imp-default.mkiv
+++ b/tex/context/base/mkiv/buff-imp-default.mkiv
@@ -15,11 +15,11 @@
\unprotect
-\definestartstop
- [DefaultSnippet]
- [\c!before=\blank,
- \c!after=\blank,
- \c!style=\tt]
+\setupstartstop
+ [DefaultSnippet]
+ [\c!before={\typingparameter\c!before},
+ \c!after={\typingparameter\c!after},
+ \c!style={\typingparameter\c!style}]
% Name
% NamePrimitive
diff --git a/tex/context/base/mkiv/buff-ini.lua b/tex/context/base/mkiv/buff-ini.lua
index 1c7912773..bd3cf9d5a 100644
--- a/tex/context/base/mkiv/buff-ini.lua
+++ b/tex/context/base/mkiv/buff-ini.lua
@@ -167,7 +167,8 @@ local function collectcontent(name,separator) -- no print
elseif nnames == 1 then
return getcontent(names[1])
else
- local t, n = { }, 0
+ local t = { }
+ local n = 0
for i=1,nnames do
local c = getcontent(names[i])
if c ~= "" then
@@ -182,7 +183,7 @@ local function collectcontent(name,separator) -- no print
end
local function loadcontent(name) -- no print
- local content = collectcontent(name,"\n") -- tex likes \n
+ local content = collectcontent(name,"\n") -- tex likes \n hm, elsewhere \r
local ok, err = load(content)
if ok then
return ok()
@@ -645,7 +646,10 @@ local function gettexbuffer(name)
end
end
-buffers.run = runbuffer
+buffers.get = getbuffer
+buffers.getmkiv = getbuffermkiv
+buffers.gettexbuffer = gettexbuffer
+buffers.run = runbuffer
implement { name = "getbufferctxlua", actions = loadcontent, arguments = "string" }
implement { name = "getbuffer", actions = getbuffer, arguments = "string" }
@@ -708,3 +712,18 @@ do
end
end
+
+-- moved here:
+
+function buffers.samplefile(name)
+ if not buffers.exists(name) then
+ buffers.assign(name,io.loaddata(resolvers.findfile(name)))
+ end
+ buffers.get(name)
+end
+
+implement {
+ name = "samplefile", -- bad name, maybe rename to injectbuffercontent
+ actions = buffers.samplefile,
+ arguments = "string"
+}
diff --git a/tex/context/base/mkiv/buff-ini.mkiv b/tex/context/base/mkiv/buff-ini.mkiv
index 1a5ce4591..145f0f392 100644
--- a/tex/context/base/mkiv/buff-ini.mkiv
+++ b/tex/context/base/mkiv/buff-ini.mkiv
@@ -44,8 +44,18 @@
% \def\buff_start_indeed#1#2#3#4#5% \donothing needed ! #5=undent)
% {\normalexpanded{\buff_pickup{#2}{#3}{#4}{}{\buff_stop{#4}}\plusone}}
+% \def\buff_start_indeed#1#2#3#4%
+% {\normalexpanded{\buff_pickup{#2}{#3}{#4}{}{\buff_stop{#4}}\plusone}}
+
\def\buff_start_indeed#1#2#3#4%
- {\normalexpanded{\buff_pickup{#2}{#3}{#4}{}{\buff_stop{#4}}\plusone}}
+ {\edef\p_strip{\namedbufferparameter{#1}\c!strip}% for aditya
+ \normalexpanded{\buff_pickup
+ {#2}%
+ {#3}%
+ {#4}%
+ {}%
+ {\buff_stop{#4}}%
+ \ifx\p_strip\v!no\zerocount\else\plusone\fi}}
\unexpanded\def\grabbufferdata % was: \dostartbuffer
{\begingroup % (4)
@@ -155,7 +165,7 @@
\setexpandedbufferparameter\c!number{\number\c_buff_n_of_defined}%
\edef\currentdefinedbuffer{def-\number\c_buff_n_of_defined}%
\setuevalue{\e!start\currentbuffer}{\buff_start_defined{\currentbuffer}{\currentdefinedbuffer}{\e!start\currentbuffer}{\e!stop\currentbuffer}}%
- \setuevalue{\e!get\currentbuffer }{\buff_get_stored{\currentbuffer}{\currentdefinedbuffer}}%
+ \setuevalue{\e!get \currentbuffer}{\buff_get_stored {\currentbuffer}{\currentdefinedbuffer}}%
\to \everydefinebuffer
\unexpanded\def\buff_start_defined
@@ -169,16 +179,16 @@
{\dosingleempty\buff_get}
\unexpanded\def\buff_get[#1]% [name]
- {\namedbufferparameter\empty\c!before
+ {\namedbufferparameter\empty\c!before\relax
\doifelsenothing{#1}
{\buff_get_stored_indeed\empty}
{\processcommalist[#1]\buff_get_stored_indeed}%
- \namedbufferparameter\empty\c!after}
+ \namedbufferparameter\empty\c!after\relax}
\unexpanded\def\buff_get_stored#1#2%
- {\namedbufferparameter{#1}\c!before
+ {\namedbufferparameter{#1}\c!before\relax
\buff_get_stored_indeed{#2}%
- \namedbufferparameter{#1}\c!after}
+ \namedbufferparameter{#1}\c!after\relax}
\unexpanded\def\buff_get_stored_indeed#1%
{\clf_getbuffer{#1}}
@@ -274,28 +284,4 @@
\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/mkiv/buff-ver.lua b/tex/context/base/mkiv/buff-ver.lua
index d9178b1df..88605631d 100644
--- a/tex/context/base/mkiv/buff-ver.lua
+++ b/tex/context/base/mkiv/buff-ver.lua
@@ -43,6 +43,7 @@ local findfile = resolvers.findfile
local addsuffix = file.addsuffix
local v_yes = variables.yes
+local v_no = variables.no
local v_last = variables.last
local v_all = variables.all
local v_absolute = variables.absolute
@@ -141,7 +142,8 @@ local functions = { __index = {
local handlers = { }
function visualizers.newhandler(name,data)
- local tname, tdata = type(name), type(data)
+ local tname = type(name)
+ local tdata = type(data)
if tname == "table" then -- (data)
setmetatable(name,getmetatable(name) or functions)
return name
@@ -255,7 +257,7 @@ function visualizers.load(name)
if trace_visualize then
report_visualizers("loading visualizer %a",name)
end
- lua.registercode(luaname)
+ lua.registercode(luaname) -- only used here, end up in format
context.input(texname)
end
if rawget(specifications,name) == nil then
@@ -445,7 +447,7 @@ function visualizers.registerescapecommand(name,token,normalmethod,escapecommand
end
token = P(token)
local notoken = hack((1 - token)^1)
- local cstoken = name_pattern * space_pattern
+ local cstoken = Cs(name_pattern * (space_pattern/""))
escapepattern = (
(token / "")
* (cstoken / (escapecommand or texcommand))
@@ -614,7 +616,12 @@ end
local onlyspaces = S(" \t\f\n\r")^0 * P(-1)
local function getstrip(lines,first,last)
- local first, last = first or 1, last or #lines
+ if not first then
+ first = 1
+ end
+ if not last then
+ last = #lines
+ end
for i=first,last do
local li = lines[i]
if #li == 0 or lpegmatch(onlyspaces,li) then
@@ -736,12 +743,14 @@ end
local function filter(lines,settings) -- todo: inline or display in settings
local strip = settings.strip
- if strip and strip ~= "" then
+ -- if strip and strip == "" then
+ if strip ~= v_no and strip ~= false then
lines = realign(lines,strip)
end
- local line, n = 0, 0
- local first, last, m = getstrip(lines)
+ local line = 0
+ local n = 0
local range = settings.range
+ local first, last, m = getstrip(lines)
if range then
first, last = getrange(lines,first,last,range)
first, last = getstrip(lines,first,last)
diff --git a/tex/context/base/mkiv/buff-ver.mkiv b/tex/context/base/mkiv/buff-ver.mkiv
index 558049dcc..7cf829b74 100644
--- a/tex/context/base/mkiv/buff-ver.mkiv
+++ b/tex/context/base/mkiv/buff-ver.mkiv
@@ -496,7 +496,7 @@
\def\buff_verbatim_typing_start_nop
{\typingparameter\c!before
- \startpacked[\v!blank]
+ \startpacked[\v!blank]%
\buff_verbatim_setup_line_numbering
\buff_verbatim_initialize_typing_one
\buff_verbatim_setup_keep_together
@@ -504,7 +504,7 @@
\def\buff_verbatim_typing_start_yes[#1]%
{\typingparameter\c!before
- \startpacked[\v!blank]
+ \startpacked[\v!blank]%
\doifelseassignment{#1}
{\setupcurrenttyping[#1]}
{\doif\v!continue{#1}{\lettypingparameter\c!continue\v!yes}}%
@@ -514,9 +514,16 @@
\normalexpanded{\buff_verbatim_type_block{\e!start\currenttyping}{\e!stop\currenttyping}}}
\unexpanded\def\buff_verbatim_type_block#1#2%
- {\buff_pickup{_typing_}{#1}{#2}{}{\buff_verbatim_type_block_verbatim_indeed{#1}{#2}}\plusone} % was dowithbuffer
-
-\def\buff_verbatim_type_block_verbatim_indeed#1#2%
+ {\edef\p_strip{\typingparameter\c!strip}%
+ \normalexpanded{\buff_pickup
+ {_typing_}%
+ {#1}%
+ {#2}%
+ {}%
+ {\buff_verbatim_type_block_verbatim_indeed{#1}{#2}}%
+ \ifx\p_strip\v!no\zerocount\else\plusone\fi}}
+
+\unexpanded\def\buff_verbatim_type_block_verbatim_indeed#1#2%
{\buff_verbatim_initialize_typing_two
\dostarttaggedchained\t!verbatimblock\currenttyping\??typing
\beginofverbatimlines
@@ -533,7 +540,7 @@
\dostoptagged
\endofverbatimlines
\dostoptagged
- \csname#2\endcsname}
+ \begincsname#2\endcsname}
\unexpanded\def\buff_verbatim_typing_stop#1% hm, currenttyping
{\stoppacked
diff --git a/tex/context/base/mkiv/catc-ini.mkiv b/tex/context/base/mkiv/catc-ini.mkiv
index 471e4d1c8..215ec14e1 100644
--- a/tex/context/base/mkiv/catc-ini.mkiv
+++ b/tex/context/base/mkiv/catc-ini.mkiv
@@ -23,58 +23,110 @@
%D \MKII\ file. There is some overlap in code with \MKII\ but we take that
%D for granted. Also, in \MKIV\ less active characters are used.
-\setnewconstant\escapecatcode 0
-\setnewconstant\begingroupcatcode 1
-\setnewconstant\endgroupcatcode 2
-\setnewconstant\mathshiftcatcode 3
-\setnewconstant\alignmentcatcode 4
-\setnewconstant\endoflinecatcode 5
-\setnewconstant\parametercatcode 6
-\setnewconstant\superscriptcatcode 7
-\setnewconstant\subscriptcatcode 8
-\setnewconstant\ignorecatcode 9
-\setnewconstant\spacecatcode 10
-\setnewconstant\lettercatcode 11
-\setnewconstant\othercatcode 12 % finally obsolete: \let\other \othercatcode
-\setnewconstant\activecatcode 13 % finally obsolete: \let\active\activecatcode
-\setnewconstant\commentcatcode 14
-\setnewconstant\invalidcatcode 15
-
-\setnewconstant\tabasciicode 9
-\setnewconstant\newlineasciicode 10 % don't confuse this one with \endoflineasciicode
-\setnewconstant\formfeedasciicode 12
-\setnewconstant\endoflineasciicode 13 % somewhat messy but this can be the active \par
-\setnewconstant\endoffileasciicode 26
-\setnewconstant\spaceasciicode 32
-\setnewconstant\exclamationmarkasciicode 33 % ! used in namespace protection
-\setnewconstant\doublequoteasciicode 34 % "
-\setnewconstant\hashasciicode 35
-\setnewconstant\dollarasciicode 36
-\setnewconstant\commentasciicode 37
-\setnewconstant\ampersandasciicode 38
-\setnewconstant\singlequoteasciicode 39 % '
-\setnewconstant\primeasciicode 39 % '
-\setnewconstant\hyphenasciicode 45
-\setnewconstant\forwardslashasciicode 47 % /
-\setnewconstant\colonasciicode 58
-\setnewconstant\lessthanasciicode 60 % < used as alternative verbatim {
-\setnewconstant\morethanasciicode 62 % > used as alternative verbatim }
-\setnewconstant\questionmarkasciicode 63 % ? used in namespace protection
-\setnewconstant\atsignasciicode 64 % @ used in namespace protection
-\setnewconstant\backslashasciicode 92 % `\\
-\setnewconstant\circumflexasciicode 94
-\setnewconstant\underscoreasciicode 95
-\setnewconstant\leftbraceasciicode 123 % `\{
-\setnewconstant\barasciicode 124 % `\|
-\setnewconstant\rightbraceasciicode 125 % `\}
-\setnewconstant\tildeasciicode 126 % `\~
-\setnewconstant\delasciicode 127
+% \normalprotected\def\setnewconstantfromchar#1%
+% {\expandafter\ifdefined\expandafter#1\expandafter
+% \let\expandafter#1\expandafter\undefined\expandafter\fi\expandafter
+% \newcount\expandafter#1\expandafter#1\the#1\relax}
+%
+% \normalprotected\def\setnewconstantfromchar#1%
+% {\begingroup
+% \scratchcounter#1%
+% \edef\!!stringa{\meaning#1}%
+% \chardef#1\scratchcounter
+% \edef\!!stringb{\meaning#1}%
+% \normalexpanded{\endgroup
+% \ifx\!!stringa\!!stringb
+% \let#1\noexpand\undefined
+% \newcount#1%
+% \fi
+% #1\the\scratchcounter\relax}}
+%
+% \normalprotected\def\setnewconstantfromchar#1%
+% {\begingroup
+% \edef\!!stringa{\meaning#1}%
+% \expandafter\chardef\expandafter#1\the#1%
+% \edef\!!stringb{\meaning#1}%
+% \normalexpanded{\endgroup
+% \ifx\!!stringa\!!stringb
+% \let#1\noexpand\undefined
+% \newcount#1%
+% \fi
+% #1\the#1\relax}}
+%
+% \normalprotected\def\setnewconstantfromchar#1%
+% {\scratchcounter#1\let#1\undefined\newcount#1#1\scratchcounter}
+
+\def\promote#1{\scratchcounter#1\let#1\undefined\newcount#1#1\scratchcounter}
+
+\promote\escapecatcode
+\promote\begingroupcatcode
+\promote\endgroupcatcode
+\promote\mathshiftcatcode
+\promote\alignmentcatcode
+\promote\endoflinecatcode
+\promote\parametercatcode
+\promote\superscriptcatcode
+\promote\subscriptcatcode
+\promote\ignorecatcode
+\promote\spacecatcode
+\promote\lettercatcode
+\promote\othercatcode
+\promote\activecatcode
+\promote\commentcatcode
+\promote\invalidcatcode
+
+\promote\tabasciicode
+\promote\newlineasciicode
+\promote\formfeedasciicode
+\promote\endoflineasciicode
+\promote\endoffileasciicode
+\promote\spaceasciicode
+\promote\exclamationmarkasciicode
+\promote\doublequoteasciicode
+\promote\hashasciicode
+\promote\dollarasciicode
+\promote\commentasciicode
+\promote\ampersandasciicode
+\promote\singlequoteasciicode
+\promote\primeasciicode
+\promote\hyphenasciicode
+\promote\forwardslashasciicode
+\promote\colonasciicode
+\promote\lessthanasciicode
+\promote\morethanasciicode
+\promote\questionmarkasciicode
+\promote\atsignasciicode
+\promote\backslashasciicode
+\promote\circumflexasciicode
+\promote\underscoreasciicode
+\promote\leftbraceasciicode
+\promote\barasciicode
+\promote\rightbraceasciicode
+\promote\tildeasciicode
+\promote\delasciicode
+
+\let\promote\undefined
+
+% \begingroup
+%
+% \catcode\tabasciicode \activecatcode
+% \catcode\formfeedasciicode \activecatcode
+% \catcode\endoflineasciicode\activecatcode
+%
+% \letcharcode\tabasciicode \relax
+% \letcharcode\newlineasciicode \relax
+% \letcharcode\formfeedasciicode \relax
+% \letcharcode\endoflineasciicode\relax
+%
+% \xdef\activetabtoken {\Uchar\tabasciicode } % \gdef\activetabtoken {^^I}
+% \xdef\outputnewlinechar {\Uchar\newlineasciicode } % \gdef\outputnewlinechar {^^J}
+% \xdef\activeformfeedtoken {\Uchar\formfeedasciicode } % \gdef\activeformfeedtoken {^^L}
+% \xdef\activeendoflinetoken{\Uchar\endoflineasciicode} % \gdef\activeendoflinetoken{^^M}
+%
+% \endgroup
\begingroup
- \catcode \tabasciicode \activecatcode \gdef\activetabtoken {^^I}
- \gdef\outputnewlinechar {^^J}
- \catcode \formfeedasciicode \activecatcode \gdef\activeformfeedtoken {^^L}
- \catcode \endoflineasciicode \activecatcode \gdef\activeendoflinetoken{^^M}
+ \letcharcode\newlineasciicode\relax \xdef\outputnewlinechar{\Uchar\newlineasciicode}
\endgroup
% \endlinechar = \endoflineasciicode % appended to input lines
@@ -82,10 +134,17 @@
% rather special and used in writing to file: \let\par\outputnewlinechar
+% \normalprotected\def\initializenewlinechar % operating system dependent
+% {\begingroup
+% \newlinechar\newlineasciicode
+% \xdef\outputnewlinechar{^^J}%
+% \endgroup}
+
\normalprotected\def\initializenewlinechar % operating system dependent
{\begingroup
+ \letcharcode\newlineasciicode\relax
\newlinechar\newlineasciicode
- \xdef\outputnewlinechar{^^J}%
+ \xdef\outputnewlinechar{\Uchar\newlineasciicode}%
\endgroup}
%D We predefine some prefixes ahead of syst-aux and mult-sys.
diff --git a/tex/context/base/mkiv/char-act.mkiv b/tex/context/base/mkiv/char-act.mkiv
index 7d7268c8b..dd9a325f2 100644
--- a/tex/context/base/mkiv/char-act.mkiv
+++ b/tex/context/base/mkiv/char-act.mkiv
@@ -44,11 +44,14 @@
\unexpanded\def\controlspace{\hbox{\asciispacechar}} % rather tex, we need the unicode value
\unexpanded\def\normalspaces{\catcode\spaceasciicode\spacecatcode}
-\bgroup
- \catcode\spaceasciicode\activecatcode
- \unexpanded\gdef\obeyspaces{\catcode\spaceasciicode\activecatcode\def {\obeyedspace}}
- \unexpanded\gdef\setcontrolspaces{\catcode\spaceasciicode\activecatcode\def {\controlspace}}
-\egroup
+% \bgroup
+% \catcode\spaceasciicode\activecatcode
+% \unexpanded\gdef\obeyspaces {\catcode\spaceasciicode\activecatcode\def {\obeyedspace }}
+% \unexpanded\gdef\setcontrolspaces{\catcode\spaceasciicode\activecatcode\def {\controlspace}}
+% \egroup
+
+%unexpanded\def\obeyspaces {\catcode\spaceasciicode\activecatcode\letcharcode\spaceasciicode\obeyedspace }
+\unexpanded\def\setcontrolspaces{\catcode\spaceasciicode\activecatcode\letcharcode\spaceasciicode\controlspace}
%D \macros
%D {obeytabs, obeylines, obeypages,ignoretabs, ignorelines, ignorepages}
@@ -59,20 +62,42 @@
%D \NEWPAGE\ character locally, we redefine the meaning of
%D this (often already) active character.
-\expandafter\def\activeformfeedtoken{\par}
+% \expandafter\def\activeformfeedtoken{\par}
+
+\letcharcode\formfeedasciicode\par
%D The following indirect definitions enable us to implement
%D all kind of \type{\obeyed} handlers.
-\unexpanded\def\obeytabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedtab }}
-\unexpanded\def\obeylines {\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedline}}
-\unexpanded\def\obeypages {\catcode\formfeedasciicode \activecatcode\expandafter\def\activeformfeedtoken {\obeyedpage}}
+% \unexpanded\def\obeytabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedtab }}
+% \unexpanded\def\obeylines {\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedline}}
+% \unexpanded\def\obeypages {\catcode\formfeedasciicode \activecatcode\expandafter\def\activeformfeedtoken {\obeyedpage}}
+
+% \unexpanded\def\ignoretabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedspace}}
+% \unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedspace}}
+% \unexpanded\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode}
+% \unexpanded\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode}
+
+% but ... as we don't want to freeze to \obeyedspace etc which can be set after \obeyspaces, we
+% use an idirectness
-\unexpanded\def\ignoretabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedspace}}
-\unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedspace}}
+\def\_obeyed_space_{\obeyedspace}
+\def\_obeyed_tab_ {\obeyedtab}
+\def\_obeyed_line_ {\obeyedline}
+\def\_obeyed_page_ {\obeyedpage}
+
+\unexpanded\def\obeyspaces {\catcode\spaceasciicode \activecatcode\letcharcode\spaceasciicode \_obeyed_space_}
+\unexpanded\def\obeytabs {\catcode\tabasciicode \activecatcode\letcharcode\tabasciicode \_obeyed_tab_}
+\unexpanded\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\_obeyed_line_}
+\unexpanded\def\obeypages {\catcode\formfeedasciicode \activecatcode\letcharcode\formfeedasciicode \_obeyed_page_}
+
+\unexpanded\def\ignoretabs {\catcode\tabasciicode \activecatcode\letcharcode\tabasciicode \_obeyed_space_}
+\unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\_obeyed_space_}
\unexpanded\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode}
\unexpanded\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode}
+\unexpanded\def\setcontrolspaces{\catcode\spaceasciicode\activecatcode\letcharcode\spaceasciicode\_control_space_}
+
%D \macros
%D {naturaltextext}
%D
diff --git a/tex/context/base/mkiv/char-def.lua b/tex/context/base/mkiv/char-def.lua
index fcbf01900..c17400a79 100644
--- a/tex/context/base/mkiv/char-def.lua
+++ b/tex/context/base/mkiv/char-def.lua
@@ -10232,6 +10232,7 @@ characters.data={
[0x3D0]={
adobename="betasymbolgreek",
category="ll",
+ contextname="greekbetaalt",
description="GREEK BETA SYMBOL",
direction="l",
linebreak="al",
@@ -14164,6 +14165,13 @@ characters.data={
synonyms={ "armenian patiw" },
unicodeslot=0x55F,
},
+ [0x560]={
+ category="ll",
+ description="ARMENIAN SMALL LETTER TURNED AYB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x560,
+ },
[0x561]={
adobename="aybarmenian",
category="ll",
@@ -14515,6 +14523,13 @@ characters.data={
specials={ "compat", 0x565, 0x582 },
unicodeslot=0x587,
},
+ [0x588]={
+ category="ll",
+ description="ARMENIAN SMALL LETTER YI WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x588,
+ },
[0x589]={
adobename="periodarmenian",
category="po",
@@ -15283,6 +15298,13 @@ characters.data={
linebreak="hl",
unicodeslot=0x5EA,
},
+ [0x5EF]={
+ category="lo",
+ description="HEBREW YOD TRIANGLE",
+ direction="r",
+ linebreak="hl",
+ unicodeslot=0x5EF,
+ },
[0x5F0]={
adobename="vavvavhebrew",
category="lo",
@@ -17638,6 +17660,7 @@ characters.data={
unicodeslot=0x70D,
},
[0x70F]={
+ arabic="t",
category="cf",
description="SYRIAC ABBREVIATION MARK",
direction="al",
@@ -19362,6 +19385,28 @@ characters.data={
linebreak="al",
unicodeslot=0x7FA,
},
+ [0x7FD]={
+ category="mn",
+ combining=0xDC,
+ description="NKO DANTAYALAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x7FD,
+ },
+ [0x7FE]={
+ category="sc",
+ description="NKO DOROME SIGN",
+ direction="r",
+ linebreak="pr",
+ unicodeslot=0x7FE,
+ },
+ [0x7FF]={
+ category="sc",
+ description="NKO TAMAN SIGN",
+ direction="r",
+ linebreak="pr",
+ unicodeslot=0x7FF,
+ },
[0x800]={
category="lo",
description="SAMARITAN LETTER ALAF",
@@ -20361,6 +20406,14 @@ characters.data={
linebreak="al",
unicodeslot=0x8BD,
},
+ [0x8D3]={
+ category="mn",
+ combining=0xDC,
+ description="ARABIC SMALL LOW WAW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x8D3,
+ },
[0x8D4]={
category="mn",
combining=0xE6,
@@ -21284,8 +21337,8 @@ characters.data={
description="DEVANAGARI SIGN NUKTA",
direction="nsm",
indic="o",
- indicmark="b",
indicclass="nukta",
+ indicmark="b",
linebreak="cm",
unicodeslot=0x93C,
},
@@ -21522,8 +21575,8 @@ characters.data={
description="DEVANAGARI STRESS SIGN ANUDATTA",
direction="nsm",
indic="s",
- indicmark="b",
indicclass="anudatta",
+ indicmark="b",
linebreak="cm",
unicodeslot=0x952,
},
@@ -22376,8 +22429,8 @@ characters.data={
description="BENGALI SIGN NUKTA",
direction="nsm",
indic="o",
- indicmark="b",
indicclass="nukta",
+ indicmark="b",
linebreak="cm",
unicodeslot=0x9BC,
},
@@ -22823,6 +22876,14 @@ characters.data={
linebreak="al",
unicodeslot=0x9FD,
},
+ [0x9FE]={
+ category="mn",
+ combining=0xE6,
+ description="BENGALI SANDHI MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x9FE,
+ },
[0xA01]={
category="mn",
description="GURMUKHI SIGN ADAK BINDI",
@@ -23247,8 +23308,8 @@ characters.data={
description="GURMUKHI SIGN NUKTA",
direction="nsm",
indic="o",
- indicmark="b",
indicclass="nukta",
+ indicmark="b",
linebreak="cm",
unicodeslot=0xA3C,
},
@@ -23565,6 +23626,13 @@ characters.data={
linebreak="cm",
unicodeslot=0xA75,
},
+ [0xA76]={
+ category="po",
+ description="GURMUKHI ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76,
+ },
[0xA81]={
adobename="candrabindugujarati",
category="mn",
@@ -24032,8 +24100,8 @@ characters.data={
description="GUJARATI SIGN NUKTA",
direction="nsm",
indic="o",
- indicmark="b",
indicclass="nukta",
+ indicmark="b",
linebreak="cm",
unicodeslot=0xABC,
},
@@ -24807,8 +24875,8 @@ characters.data={
description="ORIYA SIGN NUKTA",
direction="nsm",
indic="o",
- indicmark="b",
indicclass="nukta",
+ indicmark="b",
linebreak="cm",
unicodeslot=0xB3C,
},
@@ -25809,6 +25877,13 @@ characters.data={
linebreak="cm",
unicodeslot=0xC03,
},
+ [0xC04]={
+ category="mn",
+ description="TELUGU SIGN COMBINING ANUSVARA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xC04,
+ },
[0xC05]={
category="lo",
description="TELUGU LETTER A",
@@ -26175,9 +26250,9 @@ characters.data={
category="lo",
description="TELUGU LETTER VA",
direction="l",
+ indic="c",
linebreak="al",
unicodeslot=0xC35,
- indic="c",
},
[0xC36]={
category="lo",
@@ -26614,6 +26689,13 @@ characters.data={
linebreak="cm",
unicodeslot=0xC83,
},
+ [0xC84]={
+ category="po",
+ description="KANNADA SIGN SIDDHAM",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0xC84,
+ },
[0xC85]={
category="lo",
description="KANNADA LETTER A",
@@ -27014,8 +27096,8 @@ characters.data={
description="KANNADA SIGN NUKTA",
direction="nsm",
indic="o",
- indicmark="b",
indicclass="nukta",
+ indicmark="b",
linebreak="cm",
unicodeslot=0xCBC,
},
@@ -31643,6 +31725,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1000,
variants={
@@ -31653,6 +31736,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1001,
},
@@ -31660,6 +31744,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER GA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1002,
variants={
@@ -31670,6 +31755,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER GHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1003,
},
@@ -31677,6 +31763,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER NGA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1004,
variants={
@@ -31687,6 +31774,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER CA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1005,
},
@@ -31694,6 +31782,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER CHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1006,
},
@@ -31701,6 +31790,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER JA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1007,
},
@@ -31708,6 +31798,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER JHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1008,
},
@@ -31715,6 +31806,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER NYA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1009,
},
@@ -31722,6 +31814,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER NNYA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x100A,
},
@@ -31729,6 +31822,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TTA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x100B,
},
@@ -31736,6 +31830,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TTHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x100C,
},
@@ -31743,6 +31838,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER DDA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x100D,
},
@@ -31750,6 +31846,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER DDHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x100E,
},
@@ -31757,6 +31854,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER NNA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x100F,
},
@@ -31764,6 +31862,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1010,
variants={
@@ -31774,6 +31873,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER THA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1011,
variants={
@@ -31784,6 +31884,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER DA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1012,
},
@@ -31791,6 +31892,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER DHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1013,
},
@@ -31798,6 +31900,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER NA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1014,
},
@@ -31805,6 +31908,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER PA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1015,
variants={
@@ -31815,6 +31919,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER PHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1016,
},
@@ -31822,6 +31927,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER BA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1017,
},
@@ -31829,6 +31935,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER BHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1018,
},
@@ -31836,6 +31943,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER MA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1019,
variants={
@@ -31846,6 +31954,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER YA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x101A,
variants={
@@ -31856,6 +31965,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER RA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x101B,
},
@@ -31863,6 +31973,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER LA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x101C,
variants={
@@ -31873,6 +31984,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER WA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x101D,
variants={
@@ -31883,6 +31995,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x101E,
},
@@ -31890,6 +32003,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER HA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x101F,
},
@@ -31897,6 +32011,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER LLA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1020,
},
@@ -31904,6 +32019,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER A",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x1021,
},
@@ -31911,6 +32027,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN A",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x1022,
variants={
@@ -31921,6 +32038,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER I",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x1023,
},
@@ -31928,6 +32046,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER II",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x1024,
},
@@ -31935,6 +32054,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER U",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x1025,
},
@@ -31942,6 +32062,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER UU",
direction="l",
+ indic="i",
linebreak="sa",
specials={ "char", 0x1025, 0x102E },
unicodeslot=0x1026,
@@ -31950,6 +32071,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER E",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x1027,
},
@@ -31957,6 +32079,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER MON E",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x1028,
},
@@ -31964,6 +32087,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER O",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x1029,
},
@@ -31971,6 +32095,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER AU",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x102A,
},
@@ -31978,6 +32103,8 @@ characters.data={
category="mc",
description="MYANMAR VOWEL SIGN TALL AA",
direction="l",
+ indic="d",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x102B,
},
@@ -31985,6 +32112,8 @@ characters.data={
category="mc",
description="MYANMAR VOWEL SIGN AA",
direction="l",
+ indic="d",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x102C,
},
@@ -31992,6 +32121,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN I",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x102D,
},
@@ -31999,6 +32130,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN II",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x102E,
},
@@ -32006,6 +32139,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN U",
direction="nsm",
+ indic="d",
+ indicmark="b",
linebreak="sa",
unicodeslot=0x102F,
},
@@ -32013,6 +32148,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN UU",
direction="nsm",
+ indic="d",
+ indicmark="b",
linebreak="sa",
unicodeslot=0x1030,
},
@@ -32020,6 +32157,8 @@ characters.data={
category="mc",
description="MYANMAR VOWEL SIGN E",
direction="l",
+ indic="d",
+ indicmark="l",
linebreak="sa",
unicodeslot=0x1031,
variants={
@@ -32030,6 +32169,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN AI",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x1032,
},
@@ -32037,6 +32178,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN MON II",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x1033,
},
@@ -32044,6 +32187,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN MON O",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x1034,
},
@@ -32051,6 +32196,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN E ABOVE",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x1035,
},
@@ -32058,6 +32205,8 @@ characters.data={
category="mn",
description="MYANMAR SIGN ANUSVARA",
direction="nsm",
+ indic="m",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x1036,
},
@@ -32066,6 +32215,8 @@ characters.data={
combining=0x7,
description="MYANMAR SIGN DOT BELOW",
direction="nsm",
+ indic="s",
+ indicmark="b",
linebreak="sa",
unicodeslot=0x1037,
},
@@ -32073,6 +32224,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN VISARGA",
direction="l",
+ indic="m",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1038,
},
@@ -32081,6 +32234,8 @@ characters.data={
combining=0x9,
description="MYANMAR SIGN VIRAMA",
direction="nsm",
+ indic="m",
+ indicmark="b",
linebreak="sa",
synonyms={ "myanmar killer" },
unicodeslot=0x1039,
@@ -32090,6 +32245,8 @@ characters.data={
combining=0x9,
description="MYANMAR SIGN ASAT",
direction="nsm",
+ indic="m",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x103A,
},
@@ -32097,6 +32254,8 @@ characters.data={
category="mc",
description="MYANMAR CONSONANT SIGN MEDIAL YA",
direction="l",
+ indic="c",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x103B,
},
@@ -32104,6 +32263,7 @@ characters.data={
category="mc",
description="MYANMAR CONSONANT SIGN MEDIAL RA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x103C,
},
@@ -32111,6 +32271,8 @@ characters.data={
category="mn",
description="MYANMAR CONSONANT SIGN MEDIAL WA",
direction="nsm",
+ indic="c",
+ indicmark="b",
linebreak="sa",
unicodeslot=0x103D,
},
@@ -32118,6 +32280,8 @@ characters.data={
category="mn",
description="MYANMAR CONSONANT SIGN MEDIAL HA",
direction="nsm",
+ indic="c",
+ indicmark="b",
linebreak="sa",
unicodeslot=0x103E,
},
@@ -32125,6 +32289,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER GREAT SA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x103F,
},
@@ -32132,6 +32297,7 @@ characters.data={
category="nd",
description="MYANMAR DIGIT ZERO",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1040,
},
@@ -32139,6 +32305,7 @@ characters.data={
category="nd",
description="MYANMAR DIGIT ONE",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1041,
},
@@ -32146,6 +32313,7 @@ characters.data={
category="nd",
description="MYANMAR DIGIT TWO",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1042,
},
@@ -32153,6 +32321,7 @@ characters.data={
category="nd",
description="MYANMAR DIGIT THREE",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1043,
},
@@ -32160,6 +32329,7 @@ characters.data={
category="nd",
description="MYANMAR DIGIT FOUR",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1044,
},
@@ -32167,6 +32337,7 @@ characters.data={
category="nd",
description="MYANMAR DIGIT FIVE",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1045,
},
@@ -32174,6 +32345,7 @@ characters.data={
category="nd",
description="MYANMAR DIGIT SIX",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1046,
},
@@ -32181,6 +32353,7 @@ characters.data={
category="nd",
description="MYANMAR DIGIT SEVEN",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1047,
},
@@ -32188,6 +32361,7 @@ characters.data={
category="nd",
description="MYANMAR DIGIT EIGHT",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1048,
},
@@ -32195,6 +32369,7 @@ characters.data={
category="nd",
description="MYANMAR DIGIT NINE",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1049,
},
@@ -32202,6 +32377,7 @@ characters.data={
category="po",
description="MYANMAR SIGN LITTLE SECTION",
direction="l",
+ indic="o",
linebreak="ba",
unicodeslot=0x104A,
},
@@ -32209,6 +32385,7 @@ characters.data={
category="po",
description="MYANMAR SIGN SECTION",
direction="l",
+ indic="o",
linebreak="ba",
unicodeslot=0x104B,
},
@@ -32216,6 +32393,7 @@ characters.data={
category="po",
description="MYANMAR SYMBOL LOCATIVE",
direction="l",
+ indic="o",
linebreak="al",
unicodeslot=0x104C,
},
@@ -32223,6 +32401,7 @@ characters.data={
category="po",
description="MYANMAR SYMBOL COMPLETED",
direction="l",
+ indic="o",
linebreak="al",
unicodeslot=0x104D,
},
@@ -32230,6 +32409,7 @@ characters.data={
category="po",
description="MYANMAR SYMBOL AFOREMENTIONED",
direction="l",
+ indic="o",
linebreak="al",
unicodeslot=0x104E,
},
@@ -32237,6 +32417,7 @@ characters.data={
category="po",
description="MYANMAR SYMBOL GENITIVE",
direction="l",
+ indic="o",
linebreak="al",
unicodeslot=0x104F,
},
@@ -32244,6 +32425,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1050,
},
@@ -32251,6 +32433,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SSA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1051,
},
@@ -32258,6 +32441,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER VOCALIC R",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x1052,
},
@@ -32265,6 +32449,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER VOCALIC RR",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x1053,
},
@@ -32272,6 +32457,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER VOCALIC L",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x1054,
},
@@ -32279,6 +32465,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER VOCALIC LL",
direction="l",
+ indic="i",
linebreak="sa",
unicodeslot=0x1055,
},
@@ -32286,6 +32473,8 @@ characters.data={
category="mc",
description="MYANMAR VOWEL SIGN VOCALIC R",
direction="l",
+ indic="d",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1056,
},
@@ -32293,6 +32482,8 @@ characters.data={
category="mc",
description="MYANMAR VOWEL SIGN VOCALIC RR",
direction="l",
+ indic="d",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1057,
},
@@ -32300,6 +32491,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN VOCALIC L",
direction="nsm",
+ indic="d",
+ indicmark="b",
linebreak="sa",
unicodeslot=0x1058,
},
@@ -32307,6 +32500,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN VOCALIC LL",
direction="nsm",
+ indic="d",
+ indicmark="b",
linebreak="sa",
unicodeslot=0x1059,
},
@@ -32314,6 +32509,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER MON NGA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x105A,
},
@@ -32321,6 +32517,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER MON JHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x105B,
},
@@ -32328,6 +32525,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER MON BBA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x105C,
},
@@ -32335,6 +32533,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER MON BBE",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x105D,
},
@@ -32342,6 +32541,8 @@ characters.data={
category="mn",
description="MYANMAR CONSONANT SIGN MON MEDIAL NA",
direction="nsm",
+ indic="c",
+ indicmark="b",
linebreak="sa",
unicodeslot=0x105E,
},
@@ -32349,6 +32550,8 @@ characters.data={
category="mn",
description="MYANMAR CONSONANT SIGN MON MEDIAL MA",
direction="nsm",
+ indic="c",
+ indicmark="b",
linebreak="sa",
unicodeslot=0x105F,
},
@@ -32356,6 +32559,8 @@ characters.data={
category="mn",
description="MYANMAR CONSONANT SIGN MON MEDIAL LA",
direction="nsm",
+ indic="c",
+ indicmark="b",
linebreak="sa",
unicodeslot=0x1060,
},
@@ -32363,6 +32568,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SGAW KAREN SHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1061,
},
@@ -32370,6 +32576,8 @@ characters.data={
category="mc",
description="MYANMAR VOWEL SIGN SGAW KAREN EU",
direction="l",
+ indic="d",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1062,
},
@@ -32377,6 +32585,8 @@ characters.data={
category="mc",
description="MYANMAR TONE MARK SGAW KAREN HATHI",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1063,
},
@@ -32384,6 +32594,8 @@ characters.data={
category="mc",
description="MYANMAR TONE MARK SGAW KAREN KE PHO",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1064,
},
@@ -32391,6 +32603,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER WESTERN PWO KAREN THA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1065,
},
@@ -32398,6 +32611,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER WESTERN PWO KAREN PWA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1066,
},
@@ -32405,6 +32619,8 @@ characters.data={
category="mc",
description="MYANMAR VOWEL SIGN WESTERN PWO KAREN EU",
direction="l",
+ indic="d",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1067,
},
@@ -32412,6 +32628,8 @@ characters.data={
category="mc",
description="MYANMAR VOWEL SIGN WESTERN PWO KAREN UE",
direction="l",
+ indic="d",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1068,
},
@@ -32419,6 +32637,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN WESTERN PWO KAREN TONE-1",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1069,
},
@@ -32426,6 +32646,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN WESTERN PWO KAREN TONE-2",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x106A,
},
@@ -32433,6 +32655,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN WESTERN PWO KAREN TONE-3",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x106B,
},
@@ -32440,6 +32664,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN WESTERN PWO KAREN TONE-4",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x106C,
},
@@ -32447,6 +32673,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN WESTERN PWO KAREN TONE-5",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x106D,
},
@@ -32454,6 +32682,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER EASTERN PWO KAREN NNA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x106E,
},
@@ -32461,6 +32690,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER EASTERN PWO KAREN YWA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x106F,
},
@@ -32468,6 +32698,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER EASTERN PWO KAREN GHWA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1070,
},
@@ -32475,6 +32706,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN GEBA KAREN I",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x1071,
},
@@ -32482,6 +32715,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN KAYAH OE",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x1072,
},
@@ -32489,6 +32724,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN KAYAH U",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x1073,
},
@@ -32496,6 +32733,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN KAYAH EE",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x1074,
},
@@ -32503,6 +32742,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN KA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1075,
variants={
@@ -32513,6 +32753,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN KHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1076,
},
@@ -32520,6 +32761,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN GA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1077,
},
@@ -32527,6 +32769,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN CA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1078,
variants={
@@ -32537,6 +32780,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN ZA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1079,
},
@@ -32544,6 +32788,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN NYA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x107A,
variants={
@@ -32554,6 +32799,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN DA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x107B,
},
@@ -32561,6 +32807,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN NA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x107C,
},
@@ -32568,6 +32815,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN PHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x107D,
},
@@ -32575,6 +32823,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN FA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x107E,
},
@@ -32582,6 +32831,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN BA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x107F,
},
@@ -32589,6 +32839,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN THA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1080,
variants={
@@ -32599,6 +32850,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN HA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x1081,
},
@@ -32606,6 +32858,8 @@ characters.data={
category="mn",
description="MYANMAR CONSONANT SIGN SHAN MEDIAL WA",
direction="nsm",
+ indic="c",
+ indicmark="b",
linebreak="sa",
unicodeslot=0x1082,
},
@@ -32613,6 +32867,8 @@ characters.data={
category="mc",
description="MYANMAR VOWEL SIGN SHAN AA",
direction="l",
+ indic="d",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1083,
},
@@ -32620,6 +32876,8 @@ characters.data={
category="mc",
description="MYANMAR VOWEL SIGN SHAN E",
direction="l",
+ indic="d",
+ indicmark="l",
linebreak="sa",
unicodeslot=0x1084,
},
@@ -32627,6 +32885,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN SHAN E ABOVE",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x1085,
},
@@ -32634,6 +32894,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN SHAN FINAL Y",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x1086,
},
@@ -32641,6 +32903,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN SHAN TONE-2",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1087,
},
@@ -32648,6 +32912,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN SHAN TONE-3",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1088,
},
@@ -32655,6 +32921,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN SHAN TONE-5",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x1089,
},
@@ -32662,6 +32930,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN SHAN TONE-6",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x108A,
},
@@ -32669,6 +32939,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN SHAN COUNCIL TONE-2",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x108B,
},
@@ -32676,6 +32948,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN SHAN COUNCIL TONE-3",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x108C,
},
@@ -32684,6 +32958,8 @@ characters.data={
combining=0xDC,
description="MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE",
direction="nsm",
+ indic="s",
+ indicmark="b",
linebreak="sa",
unicodeslot=0x108D,
},
@@ -32691,6 +32967,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER RUMAI PALAUNG FA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0x108E,
},
@@ -32698,6 +32975,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN RUMAI PALAUNG TONE-5",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x108F,
},
@@ -32705,6 +32984,7 @@ characters.data={
category="nd",
description="MYANMAR SHAN DIGIT ZERO",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1090,
},
@@ -32712,6 +32992,7 @@ characters.data={
category="nd",
description="MYANMAR SHAN DIGIT ONE",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1091,
},
@@ -32719,6 +33000,7 @@ characters.data={
category="nd",
description="MYANMAR SHAN DIGIT TWO",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1092,
},
@@ -32726,6 +33008,7 @@ characters.data={
category="nd",
description="MYANMAR SHAN DIGIT THREE",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1093,
},
@@ -32733,6 +33016,7 @@ characters.data={
category="nd",
description="MYANMAR SHAN DIGIT FOUR",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1094,
},
@@ -32740,6 +33024,7 @@ characters.data={
category="nd",
description="MYANMAR SHAN DIGIT FIVE",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1095,
},
@@ -32747,6 +33032,7 @@ characters.data={
category="nd",
description="MYANMAR SHAN DIGIT SIX",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1096,
},
@@ -32754,6 +33040,7 @@ characters.data={
category="nd",
description="MYANMAR SHAN DIGIT SEVEN",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1097,
},
@@ -32761,6 +33048,7 @@ characters.data={
category="nd",
description="MYANMAR SHAN DIGIT EIGHT",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1098,
},
@@ -32768,6 +33056,7 @@ characters.data={
category="nd",
description="MYANMAR SHAN DIGIT NINE",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0x1099,
},
@@ -32775,6 +33064,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN KHAMTI TONE-1",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x109A,
},
@@ -32782,6 +33073,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN KHAMTI TONE-3",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x109B,
},
@@ -32789,6 +33082,8 @@ characters.data={
category="mc",
description="MYANMAR VOWEL SIGN AITON A",
direction="l",
+ indic="d",
+ indicmark="r",
linebreak="sa",
unicodeslot=0x109C,
},
@@ -32796,6 +33091,8 @@ characters.data={
category="mn",
description="MYANMAR VOWEL SIGN AITON AI",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0x109D,
},
@@ -32803,6 +33100,7 @@ characters.data={
category="so",
description="MYANMAR SYMBOL SHAN ONE",
direction="l",
+ indic="o",
linebreak="sa",
unicodeslot=0x109E,
},
@@ -32810,6 +33108,7 @@ characters.data={
category="so",
description="MYANMAR SYMBOL SHAN EXCLAMATION",
direction="l",
+ indic="o",
linebreak="sa",
unicodeslot=0x109F,
},
@@ -46377,6 +46676,14 @@ characters.data={
linebreak="al",
unicodeslot=0x1877,
},
+ [0x1878]={
+ arabic="d",
+ category="lo",
+ description="MONGOLIAN LETTER CHA WITH TWO DOTS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1878,
+ },
[0x1880]={
arabic="u",
category="lo",
@@ -52619,6 +52926,328 @@ characters.data={
linebreak="al",
unicodeslot=0x1C88,
},
+ [0x1C90]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C90,
+ },
+ [0x1C91]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER BAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C91,
+ },
+ [0x1C92]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER GAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C92,
+ },
+ [0x1C93]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER DON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C93,
+ },
+ [0x1C94]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C94,
+ },
+ [0x1C95]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER VIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C95,
+ },
+ [0x1C96]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER ZEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C96,
+ },
+ [0x1C97]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER TAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C97,
+ },
+ [0x1C98]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER IN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C98,
+ },
+ [0x1C99]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER KAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C99,
+ },
+ [0x1C9A]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER LAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C9A,
+ },
+ [0x1C9B]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER MAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C9B,
+ },
+ [0x1C9C]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER NAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C9C,
+ },
+ [0x1C9D]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER ON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C9D,
+ },
+ [0x1C9E]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER PAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C9E,
+ },
+ [0x1C9F]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER ZHAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C9F,
+ },
+ [0x1CA0]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER RAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CA0,
+ },
+ [0x1CA1]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER SAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CA1,
+ },
+ [0x1CA2]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER TAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CA2,
+ },
+ [0x1CA3]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER UN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CA3,
+ },
+ [0x1CA4]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER PHAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CA4,
+ },
+ [0x1CA5]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER KHAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CA5,
+ },
+ [0x1CA6]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER GHAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CA6,
+ },
+ [0x1CA7]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER QAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CA7,
+ },
+ [0x1CA8]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER SHIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CA8,
+ },
+ [0x1CA9]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER CHIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CA9,
+ },
+ [0x1CAA]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER CAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CAA,
+ },
+ [0x1CAB]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER JIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CAB,
+ },
+ [0x1CAC]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER CIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CAC,
+ },
+ [0x1CAD]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER CHAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CAD,
+ },
+ [0x1CAE]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER XAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CAE,
+ },
+ [0x1CAF]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER JHAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CAF,
+ },
+ [0x1CB0]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER HAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CB0,
+ },
+ [0x1CB1]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER HE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CB1,
+ },
+ [0x1CB2]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER HIE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CB2,
+ },
+ [0x1CB3]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CB3,
+ },
+ [0x1CB4]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER HAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CB4,
+ },
+ [0x1CB5]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER HOE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CB5,
+ },
+ [0x1CB6]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER FI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CB6,
+ },
+ [0x1CB7]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER YN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CB7,
+ },
+ [0x1CB8]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER ELIFI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CB8,
+ },
+ [0x1CB9]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER TURNED GAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CB9,
+ },
+ [0x1CBA]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER AIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CBA,
+ },
+ [0x1CBD]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER AEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CBD,
+ },
+ [0x1CBE]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER HARD SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CBE,
+ },
+ [0x1CBF]={
+ category="lu",
+ description="GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CBF,
+ },
[0x1CC0]={
category="po",
description="SUNDANESE PUNCTUATION BINDU SURYA",
@@ -65371,6 +66000,7 @@ characters.data={
linebreak="ai",
mathclass="ordinary",
mathname="rightangle",
+ mirror=0x2BFE,
unicodeslot=0x221F,
},
[0x2220]={
@@ -65382,6 +66012,7 @@ characters.data={
linebreak="ai",
mathclass="ordinary",
mathname="angle",
+ mirror=0x29A3,
unicodeslot=0x2220,
},
[0x2221]={
@@ -65391,6 +66022,7 @@ characters.data={
linebreak="al",
mathclass="ordinary",
mathname="measuredangle",
+ mirror=0x299B,
unicodeslot=0x2221,
},
[0x2222]={
@@ -65400,6 +66032,7 @@ characters.data={
linebreak="al",
mathclass="ordinary",
mathname="sphericalangle",
+ mirror=0x29A0,
synonyms={ "angle arc" },
unicodeslot=0x2222,
},
@@ -65430,6 +66063,7 @@ characters.data={
name="nmid",
},
},
+ mirror=0x2AEE,
specials={ "char", 0x2223, 0x338 },
unicodeslot=0x2224,
},
@@ -65834,6 +66468,7 @@ characters.data={
name="cong",
},
},
+ mirror=0x224C,
unicodeslot=0x2245,
},
[0x2246]={
@@ -65909,6 +66544,7 @@ characters.data={
direction="on",
linebreak="ai",
mathclass="relation",
+ mirror=0x2245,
unicodeslot=0x224C,
},
[0x224D]={
@@ -67110,6 +67746,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="multimap",
+ mirror=0x27DC,
unicodeslot=0x22B8,
},
[0x22B9]={
@@ -73450,8 +74087,8 @@ characters.data={
},
[0x25CC]={
adobename="dottedcircle",
- contextname="dottedcircle",
category="so",
+ contextname="dottedcircle",
description="DOTTED CIRCLE",
direction="on",
linebreak="al",
@@ -77559,6 +78196,7 @@ characters.data={
description="LEFT MULTIMAP",
direction="on",
linebreak="al",
+ mirror=0x22B8,
unicodeslot=0x27DC,
},
[0x27DD]={
@@ -80944,6 +81582,7 @@ characters.data={
description="MEASURED ANGLE OPENING LEFT",
direction="on",
linebreak="al",
+ mirror=0x2221,
unicodeslot=0x299B,
},
[0x299C]={
@@ -80979,6 +81618,7 @@ characters.data={
description="SPHERICAL ANGLE OPENING LEFT",
direction="on",
linebreak="al",
+ mirror=0x2222,
unicodeslot=0x29A0,
},
[0x29A1]={
@@ -81000,6 +81640,7 @@ characters.data={
description="REVERSED ANGLE",
direction="on",
linebreak="al",
+ mirror=0x2220,
unicodeslot=0x29A3,
},
[0x29A4]={
@@ -81007,6 +81648,7 @@ characters.data={
description="ANGLE WITH UNDERBAR",
direction="on",
linebreak="al",
+ mirror=0x29A5,
unicodeslot=0x29A4,
},
[0x29A5]={
@@ -81014,6 +81656,7 @@ characters.data={
description="REVERSED ANGLE WITH UNDERBAR",
direction="on",
linebreak="al",
+ mirror=0x29A4,
unicodeslot=0x29A5,
},
[0x29A6]={
@@ -81035,6 +81678,7 @@ characters.data={
description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT",
direction="on",
linebreak="al",
+ mirror=0x29A9,
unicodeslot=0x29A8,
},
[0x29A9]={
@@ -81042,6 +81686,7 @@ characters.data={
description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT",
direction="on",
linebreak="al",
+ mirror=0x29A8,
unicodeslot=0x29A9,
},
[0x29AA]={
@@ -81049,6 +81694,7 @@ characters.data={
description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT",
direction="on",
linebreak="al",
+ mirror=0x29AB,
unicodeslot=0x29AA,
},
[0x29AB]={
@@ -81056,6 +81702,7 @@ characters.data={
description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT",
direction="on",
linebreak="al",
+ mirror=0x29AA,
unicodeslot=0x29AB,
},
[0x29AC]={
@@ -81063,6 +81710,7 @@ characters.data={
description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP",
direction="on",
linebreak="al",
+ mirror=0x29AD,
unicodeslot=0x29AC,
},
[0x29AD]={
@@ -81070,6 +81718,7 @@ characters.data={
description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP",
direction="on",
linebreak="al",
+ mirror=0x29AC,
unicodeslot=0x29AD,
},
[0x29AE]={
@@ -81077,6 +81726,7 @@ characters.data={
description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN",
direction="on",
linebreak="al",
+ mirror=0x29AF,
unicodeslot=0x29AE,
},
[0x29AF]={
@@ -81084,6 +81734,7 @@ characters.data={
description="MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN",
direction="on",
linebreak="al",
+ mirror=0x29AE,
unicodeslot=0x29AF,
},
[0x29B0]={
@@ -81502,6 +82153,7 @@ characters.data={
description="DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK",
direction="on",
linebreak="al",
+ mirror=0x29E9,
unicodeslot=0x29E8,
},
[0x29E9]={
@@ -81509,6 +82161,7 @@ characters.data={
description="DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK",
direction="on",
linebreak="al",
+ mirror=0x29E8,
unicodeslot=0x29E9,
},
[0x29EA]={
@@ -82608,6 +83261,7 @@ characters.data={
description="LESS-THAN WITH QUESTION MARK ABOVE",
direction="on",
linebreak="al",
+ mirror=0x2A7C,
unicodeslot=0x2A7B,
},
[0x2A7C]={
@@ -82615,6 +83269,7 @@ characters.data={
description="GREATER-THAN WITH QUESTION MARK ABOVE",
direction="on",
linebreak="al",
+ mirror=0x2A7B,
unicodeslot=0x2A7C,
},
[0x2A7D]={
@@ -82692,6 +83347,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="lessapprox",
+ mirror=0x2A86,
unicodeslot=0x2A85,
},
[0x2A86]={
@@ -82701,6 +83357,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="gtrapprox",
+ mirror=0x2A85,
unicodeslot=0x2A86,
},
[0x2A87]={
@@ -82710,6 +83367,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="lneq",
+ mirror=0x2A88,
unicodeslot=0x2A87,
},
[0x2A88]={
@@ -82719,6 +83377,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="rneq",
+ mirror=0x2A87,
unicodeslot=0x2A88,
},
[0x2A89]={
@@ -82728,6 +83387,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="lnapprox",
+ mirror=0x2A8A,
unicodeslot=0x2A89,
},
[0x2A8A]={
@@ -82737,6 +83397,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="gnapprox",
+ mirror=0x2A89,
unicodeslot=0x2A8A,
},
[0x2A8B]={
@@ -82766,6 +83427,7 @@ characters.data={
description="LESS-THAN ABOVE SIMILAR OR EQUAL",
direction="on",
linebreak="al",
+ mirror=0x2A8E,
unicodeslot=0x2A8D,
},
[0x2A8E]={
@@ -82773,6 +83435,7 @@ characters.data={
description="GREATER-THAN ABOVE SIMILAR OR EQUAL",
direction="on",
linebreak="al",
+ mirror=0x2A8D,
unicodeslot=0x2A8E,
},
[0x2A8F]={
@@ -82780,6 +83443,7 @@ characters.data={
description="LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN",
direction="on",
linebreak="al",
+ mirror=0x2A90,
unicodeslot=0x2A8F,
},
[0x2A90]={
@@ -82787,6 +83451,7 @@ characters.data={
description="GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN",
direction="on",
linebreak="al",
+ mirror=0x2A8F,
unicodeslot=0x2A90,
},
[0x2A91]={
@@ -82894,6 +83559,7 @@ characters.data={
description="SIMILAR OR LESS-THAN",
direction="on",
linebreak="al",
+ mirror=0x2A9E,
unicodeslot=0x2A9D,
variants={
[0xFE00]="with similar following the slant of the upper leg",
@@ -82904,6 +83570,7 @@ characters.data={
description="SIMILAR OR GREATER-THAN",
direction="on",
linebreak="al",
+ mirror=0x2A9D,
unicodeslot=0x2A9E,
variants={
[0xFE00]="with similar following the slant of the upper leg",
@@ -82914,6 +83581,7 @@ characters.data={
description="SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN",
direction="on",
linebreak="al",
+ mirror=0x2AA0,
unicodeslot=0x2A9F,
},
[0x2AA0]={
@@ -82921,6 +83589,7 @@ characters.data={
description="SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN",
direction="on",
linebreak="al",
+ mirror=0x2A9F,
unicodeslot=0x2AA0,
},
[0x2AA1]={
@@ -83065,6 +83734,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="precneq",
+ mirror=0x2AB2,
unicodeslot=0x2AB1,
},
[0x2AB2]={
@@ -83074,6 +83744,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="succneq",
+ mirror=0x2AB1,
unicodeslot=0x2AB2,
},
[0x2AB3]={
@@ -83103,6 +83774,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="precneqq",
+ mirror=0x2AB6,
unicodeslot=0x2AB5,
},
[0x2AB6]={
@@ -83112,6 +83784,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="succneqq",
+ mirror=0x2AB5,
unicodeslot=0x2AB6,
},
[0x2AB7]={
@@ -83121,6 +83794,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="precapprox",
+ mirror=0x2AB8,
unicodeslot=0x2AB7,
},
[0x2AB8]={
@@ -83130,6 +83804,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="succapprox",
+ mirror=0x2AB7,
unicodeslot=0x2AB8,
},
[0x2AB9]={
@@ -83139,6 +83814,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="precnapprox",
+ mirror=0x2ABA,
unicodeslot=0x2AB9,
},
[0x2ABA]={
@@ -83148,6 +83824,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="succnapprox",
+ mirror=0x2AB9,
unicodeslot=0x2ABA,
},
[0x2ABB]={
@@ -83255,6 +83932,7 @@ characters.data={
description="SUBSET OF ABOVE TILDE OPERATOR",
direction="on",
linebreak="al",
+ mirror=0x2AC8,
unicodeslot=0x2AC7,
},
[0x2AC8]={
@@ -83262,6 +83940,7 @@ characters.data={
description="SUPERSET OF ABOVE TILDE OPERATOR",
direction="on",
linebreak="al",
+ mirror=0x2AC7,
unicodeslot=0x2AC8,
},
[0x2AC9]={
@@ -83269,6 +83948,7 @@ characters.data={
description="SUBSET OF ABOVE ALMOST EQUAL TO",
direction="on",
linebreak="al",
+ mirror=0x2ACA,
unicodeslot=0x2AC9,
},
[0x2ACA]={
@@ -83276,6 +83956,7 @@ characters.data={
description="SUPERSET OF ABOVE ALMOST EQUAL TO",
direction="on",
linebreak="al",
+ mirror=0x2AC9,
unicodeslot=0x2ACA,
},
[0x2ACB]={
@@ -83285,6 +83966,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="subsetneqq",
+ mirror=0x2ACC,
unicodeslot=0x2ACB,
variants={
[0xFE00]="with stroke through bottom members",
@@ -83297,6 +83979,7 @@ characters.data={
linebreak="al",
mathclass="relation",
mathname="supsetneqq",
+ mirror=0x2ACB,
unicodeslot=0x2ACC,
variants={
[0xFE00]="with stroke through bottom members",
@@ -83559,6 +84242,7 @@ characters.data={
description="DOES NOT DIVIDE WITH REVERSED NEGATION SLASH",
direction="on",
linebreak="al",
+ mirror=0x2224,
unicodeslot=0x2AEE,
},
[0x2AEF]={
@@ -84998,6 +85682,27 @@ characters.data={
synonyms={ "escape" },
unicodeslot=0x2BB9,
},
+ [0x2BBA]={
+ category="so",
+ description="OVERLAPPING WHITE SQUARES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BBA,
+ },
+ [0x2BBB]={
+ category="so",
+ description="OVERLAPPING WHITE AND BLACK SQUARES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BBB,
+ },
+ [0x2BBC]={
+ category="so",
+ description="OVERLAPPING BLACK SQUARES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BBC,
+ },
[0x2BBD]={
category="so",
description="BALLOT BOX WITH LIGHT X",
@@ -85145,6 +85850,181 @@ characters.data={
linebreak="al",
unicodeslot=0x2BD2,
},
+ [0x2BD3]={
+ category="so",
+ description="PLUTO FORM TWO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BD3,
+ },
+ [0x2BD4]={
+ category="so",
+ description="PLUTO FORM THREE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BD4,
+ },
+ [0x2BD5]={
+ category="so",
+ description="PLUTO FORM FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BD5,
+ },
+ [0x2BD6]={
+ category="so",
+ description="PLUTO FORM FIVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BD6,
+ },
+ [0x2BD7]={
+ category="so",
+ description="TRANSPLUTO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BD7,
+ },
+ [0x2BD8]={
+ category="so",
+ description="PROSERPINA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BD8,
+ },
+ [0x2BD9]={
+ category="so",
+ description="ASTRAEA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BD9,
+ },
+ [0x2BDA]={
+ category="so",
+ description="HYGIEA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BDA,
+ },
+ [0x2BDB]={
+ category="so",
+ description="PHOLUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BDB,
+ },
+ [0x2BDC]={
+ category="so",
+ description="NESSUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BDC,
+ },
+ [0x2BDD]={
+ category="so",
+ description="WHITE MOON SELENA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BDD,
+ },
+ [0x2BDE]={
+ category="so",
+ description="BLACK DIAMOND ON CROSS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BDE,
+ },
+ [0x2BDF]={
+ category="so",
+ description="TRUE LIGHT MOON ARTA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BDF,
+ },
+ [0x2BE0]={
+ category="so",
+ description="CUPIDO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BE0,
+ },
+ [0x2BE1]={
+ category="so",
+ description="HADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BE1,
+ },
+ [0x2BE2]={
+ category="so",
+ description="ZEUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BE2,
+ },
+ [0x2BE3]={
+ category="so",
+ description="KRONOS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BE3,
+ },
+ [0x2BE4]={
+ category="so",
+ description="APOLLON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BE4,
+ },
+ [0x2BE5]={
+ category="so",
+ description="ADMETOS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BE5,
+ },
+ [0x2BE6]={
+ category="so",
+ description="VULCANUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BE6,
+ },
+ [0x2BE7]={
+ category="so",
+ description="POSEIDON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BE7,
+ },
+ [0x2BE8]={
+ category="so",
+ description="LEFT HALF BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BE8,
+ },
+ [0x2BE9]={
+ category="so",
+ description="RIGHT HALF BLACK STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BE9,
+ },
+ [0x2BEA]={
+ category="so",
+ description="STAR WITH LEFT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BEA,
+ },
+ [0x2BEB]={
+ category="so",
+ description="STAR WITH RIGHT HALF BLACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BEB,
+ },
[0x2BEC]={
category="so",
description="LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS",
@@ -85173,6 +86053,112 @@ characters.data={
linebreak="al",
unicodeslot=0x2BEF,
},
+ [0x2BF0]={
+ category="so",
+ description="ERIS FORM ONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BF0,
+ },
+ [0x2BF1]={
+ category="so",
+ description="ERIS FORM TWO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BF1,
+ },
+ [0x2BF2]={
+ category="so",
+ description="SEDNA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BF2,
+ },
+ [0x2BF3]={
+ category="so",
+ description="RUSSIAN ASTROLOGICAL SYMBOL VIGINTILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BF3,
+ },
+ [0x2BF4]={
+ category="so",
+ description="RUSSIAN ASTROLOGICAL SYMBOL NOVILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BF4,
+ },
+ [0x2BF5]={
+ category="so",
+ description="RUSSIAN ASTROLOGICAL SYMBOL QUINTILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BF5,
+ },
+ [0x2BF6]={
+ category="so",
+ description="RUSSIAN ASTROLOGICAL SYMBOL BINOVILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BF6,
+ },
+ [0x2BF7]={
+ category="so",
+ description="RUSSIAN ASTROLOGICAL SYMBOL SENTAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BF7,
+ },
+ [0x2BF8]={
+ category="so",
+ description="RUSSIAN ASTROLOGICAL SYMBOL TREDECILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BF8,
+ },
+ [0x2BF9]={
+ category="so",
+ description="EQUALS SIGN WITH INFINITY BELOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BF9,
+ },
+ [0x2BFA]={
+ category="so",
+ description="UNITED SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BFA,
+ },
+ [0x2BFB]={
+ category="so",
+ description="SEPARATED SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BFB,
+ },
+ [0x2BFC]={
+ category="so",
+ description="DOUBLED SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BFC,
+ },
+ [0x2BFD]={
+ category="so",
+ description="PASSED SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2BFD,
+ },
+ [0x2BFE]={
+ category="so",
+ description="REVERSED RIGHT ANGLE",
+ direction="on",
+ linebreak="al",
+ mirror=0x221F,
+ unicodeslot=0x2BFE,
+ },
[0x2C00]={
category="lu",
description="GLAGOLITIC CAPITAL LETTER AZU",
@@ -89226,6 +90212,41 @@ characters.data={
linebreak="ba",
unicodeslot=0x2E49,
},
+ [0x2E4A]={
+ category="po",
+ description="DOTTED SOLIDUS",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E4A,
+ },
+ [0x2E4B]={
+ category="po",
+ description="TRIPLE DAGGER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E4B,
+ },
+ [0x2E4C]={
+ category="po",
+ description="MEDIEVAL COMMA",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E4C,
+ },
+ [0x2E4D]={
+ category="po",
+ description="PARAGRAPHUS MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E4D,
+ },
+ [0x2E4E]={
+ category="po",
+ description="PUNCTUS ELEVATUS MARK",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E4E,
+ },
[0x2E80]={
category="so",
cjkwd="w",
@@ -95434,6 +96455,14 @@ characters.data={
linebreak="id",
unicodeslot=0x312E,
},
+ [0x312F]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER NN",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x312F,
+ },
[0x3131]={
adobename="kiyeokkorean",
category="lo",
@@ -117174,6 +118203,13 @@ characters.data={
linebreak="al",
unicodeslot=0xA7AE,
},
+ [0xA7AF]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL Q",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7AF,
+ },
[0xA7B0]={
category="lu",
description="LATIN CAPITAL LETTER TURNED K",
@@ -117230,6 +118266,20 @@ characters.data={
linebreak="al",
unicodeslot=0xA7B7,
},
+ [0xA7B8]={
+ category="lu",
+ description="LATIN CAPITAL LETTER U WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7B8,
+ },
+ [0xA7B9]={
+ category="ll",
+ description="LATIN SMALL LETTER U WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7B9,
+ },
[0xA7F7]={
category="lo",
description="LATIN EPIGRAPHIC LETTER SIDEWAYS I",
@@ -118975,6 +120025,20 @@ characters.data={
linebreak="al",
unicodeslot=0xA8FD,
},
+ [0xA8FE]={
+ category="lo",
+ description="DEVANAGARI LETTER AY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8FE,
+ },
+ [0xA8FF]={
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN AY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8FF,
+ },
[0xA900]={
category="nd",
description="KAYAH LI DIGIT ZERO",
@@ -120449,6 +121513,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN GHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9E0,
},
@@ -120456,6 +121521,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN CHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9E1,
},
@@ -120463,6 +121529,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN JHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9E2,
},
@@ -120470,6 +121537,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN NNA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9E3,
},
@@ -120477,6 +121545,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHAN BHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9E4,
},
@@ -120484,6 +121553,8 @@ characters.data={
category="mn",
description="MYANMAR SIGN SHAN SAW",
direction="nsm",
+ indic="d",
+ indicmark="t",
linebreak="sa",
unicodeslot=0xA9E5,
},
@@ -120491,6 +121562,7 @@ characters.data={
category="lm",
description="MYANMAR MODIFIER LETTER SHAN REDUPLICATION",
direction="l",
+ indic="o",
linebreak="sa",
unicodeslot=0xA9E6,
},
@@ -120498,6 +121570,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING NYA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9E7,
},
@@ -120505,6 +121578,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING FA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9E8,
},
@@ -120512,6 +121586,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING GA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9E9,
},
@@ -120519,6 +121594,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING GHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9EA,
},
@@ -120526,6 +121602,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING JA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9EB,
},
@@ -120533,6 +121610,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING JHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9EC,
},
@@ -120540,6 +121618,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING DDA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9ED,
},
@@ -120547,6 +121626,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING DDHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9EE,
},
@@ -120554,6 +121634,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING NNA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9EF,
},
@@ -120561,6 +121642,7 @@ characters.data={
category="nd",
description="MYANMAR TAI LAING DIGIT ZERO",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0xA9F0,
},
@@ -120568,6 +121650,7 @@ characters.data={
category="nd",
description="MYANMAR TAI LAING DIGIT ONE",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0xA9F1,
},
@@ -120575,6 +121658,7 @@ characters.data={
category="nd",
description="MYANMAR TAI LAING DIGIT TWO",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0xA9F2,
},
@@ -120582,6 +121666,7 @@ characters.data={
category="nd",
description="MYANMAR TAI LAING DIGIT THREE",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0xA9F3,
},
@@ -120589,6 +121674,7 @@ characters.data={
category="nd",
description="MYANMAR TAI LAING DIGIT FOUR",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0xA9F4,
},
@@ -120596,6 +121682,7 @@ characters.data={
category="nd",
description="MYANMAR TAI LAING DIGIT FIVE",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0xA9F5,
},
@@ -120603,6 +121690,7 @@ characters.data={
category="nd",
description="MYANMAR TAI LAING DIGIT SIX",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0xA9F6,
},
@@ -120610,6 +121698,7 @@ characters.data={
category="nd",
description="MYANMAR TAI LAING DIGIT SEVEN",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0xA9F7,
},
@@ -120617,6 +121706,7 @@ characters.data={
category="nd",
description="MYANMAR TAI LAING DIGIT EIGHT",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0xA9F8,
},
@@ -120624,6 +121714,7 @@ characters.data={
category="nd",
description="MYANMAR TAI LAING DIGIT NINE",
direction="l",
+ indic="o",
linebreak="nu",
unicodeslot=0xA9F9,
},
@@ -120631,6 +121722,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING LLA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9FA,
},
@@ -120638,6 +121730,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING DA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9FB,
},
@@ -120645,6 +121738,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING DHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9FC,
},
@@ -120652,6 +121746,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING BA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9FD,
},
@@ -120659,6 +121754,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER TAI LAING BHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xA9FE,
},
@@ -121247,6 +122343,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI GA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA60,
variants={
@@ -121257,6 +122354,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI CA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA61,
variants={
@@ -121267,6 +122365,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI CHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA62,
variants={
@@ -121277,6 +122376,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI JA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA63,
variants={
@@ -121287,6 +122387,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI JHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA64,
variants={
@@ -121297,6 +122398,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI NYA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA65,
variants={
@@ -121307,6 +122409,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI TTA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA66,
variants={
@@ -121317,6 +122420,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI TTHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA67,
},
@@ -121324,6 +122428,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI DDA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA68,
},
@@ -121331,6 +122436,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI DDHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA69,
},
@@ -121338,6 +122444,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI DHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA6A,
},
@@ -121355,6 +122462,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI SA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA6C,
variants={
@@ -121365,6 +122473,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI HA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA6D,
},
@@ -121372,6 +122481,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI HHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA6E,
},
@@ -121379,6 +122489,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI FA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA6F,
variants={
@@ -121389,6 +122500,7 @@ characters.data={
category="lm",
description="MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION",
direction="l",
+ indic="o",
linebreak="sa",
unicodeslot=0xAA70,
},
@@ -121396,6 +122508,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI XA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA71,
},
@@ -121403,6 +122516,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI ZA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA72,
},
@@ -121410,6 +122524,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER KHAMTI RA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA73,
},
@@ -121417,6 +122532,7 @@ characters.data={
category="lo",
description="MYANMAR LOGOGRAM KHAMTI OAY",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA74,
},
@@ -121424,6 +122540,7 @@ characters.data={
category="lo",
description="MYANMAR LOGOGRAM KHAMTI QN",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA75,
},
@@ -121431,6 +122548,7 @@ characters.data={
category="lo",
description="MYANMAR LOGOGRAM KHAMTI HM",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA76,
},
@@ -121438,6 +122556,7 @@ characters.data={
category="so",
description="MYANMAR SYMBOL AITON EXCLAMATION",
direction="l",
+ indic="o",
linebreak="sa",
unicodeslot=0xAA77,
},
@@ -121445,6 +122564,7 @@ characters.data={
category="so",
description="MYANMAR SYMBOL AITON ONE",
direction="l",
+ indic="o",
linebreak="sa",
unicodeslot=0xAA78,
},
@@ -121452,6 +122572,7 @@ characters.data={
category="so",
description="MYANMAR SYMBOL AITON TWO",
direction="l",
+ indic="o",
linebreak="sa",
unicodeslot=0xAA79,
},
@@ -121459,6 +122580,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER AITON RA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA7A,
variants={
@@ -121469,6 +122591,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN PAO KAREN TONE",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0xAA7B,
},
@@ -121476,6 +122600,8 @@ characters.data={
category="mn",
description="MYANMAR SIGN TAI LAING TONE-2",
direction="nsm",
+ indic="s",
+ indicmark="t",
linebreak="sa",
unicodeslot=0xAA7C,
},
@@ -121483,6 +122609,8 @@ characters.data={
category="mc",
description="MYANMAR SIGN TAI LAING TONE-5",
direction="l",
+ indic="s",
+ indicmark="r",
linebreak="sa",
unicodeslot=0xAA7D,
},
@@ -121490,6 +122618,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHWE PALAUNG CHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA7E,
},
@@ -121497,6 +122626,7 @@ characters.data={
category="lo",
description="MYANMAR LETTER SHWE PALAUNG SHA",
direction="l",
+ indic="c",
linebreak="sa",
unicodeslot=0xAA7F,
},
@@ -136230,6 +137360,9 @@ characters.data={
linebreak="id",
specials={ "wide", 0x30 },
unicodeslot=0xFF10,
+ variants={
+ [0xFE00]="short diagonal stroke form",
+ },
},
[0xFF11]={
adobename="onemonospace",
@@ -150982,6 +152115,20 @@ characters.data={
linebreak="al",
unicodeslot=0x10A33,
},
+ [0x10A34]={
+ category="lo",
+ description="KHAROSHTHI LETTER TTTA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A34,
+ },
+ [0x10A35]={
+ category="lo",
+ description="KHAROSHTHI LETTER VHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A35,
+ },
[0x10A38]={
category="mn",
combining=0xE6,
@@ -151070,6 +152217,13 @@ characters.data={
linebreak="al",
unicodeslot=0x10A47,
},
+ [0x10A48]={
+ category="no",
+ description="KHAROSHTHI FRACTION ONE HALF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A48,
+ },
[0x10A50]={
category="po",
description="KHAROSHTHI PUNCTUATION DOT",
@@ -154318,6 +155472,396 @@ characters.data={
linebreak="al",
unicodeslot=0x10CFF,
},
+ [0x10D00]={
+ arabic="l",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER A",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D00,
+ },
+ [0x10D01]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER BA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D01,
+ },
+ [0x10D02]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER PA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D02,
+ },
+ [0x10D03]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER TA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D03,
+ },
+ [0x10D04]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER TTA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D04,
+ },
+ [0x10D05]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER JA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D05,
+ },
+ [0x10D06]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER CA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D06,
+ },
+ [0x10D07]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER HA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D07,
+ },
+ [0x10D08]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER KHA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D08,
+ },
+ [0x10D09]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER FA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D09,
+ },
+ [0x10D0A]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER DA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D0A,
+ },
+ [0x10D0B]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER DDA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D0B,
+ },
+ [0x10D0C]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER RA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D0C,
+ },
+ [0x10D0D]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER RRA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D0D,
+ },
+ [0x10D0E]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER ZA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D0E,
+ },
+ [0x10D0F]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER SA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D0F,
+ },
+ [0x10D10]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER SHA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D10,
+ },
+ [0x10D11]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER KA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D11,
+ },
+ [0x10D12]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER GA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D12,
+ },
+ [0x10D13]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER LA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D13,
+ },
+ [0x10D14]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER MA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D14,
+ },
+ [0x10D15]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER NA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D15,
+ },
+ [0x10D16]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER WA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D16,
+ },
+ [0x10D17]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER KINNA WA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D17,
+ },
+ [0x10D18]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER YA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D18,
+ },
+ [0x10D19]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER KINNA YA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D19,
+ },
+ [0x10D1A]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER NGA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D1A,
+ },
+ [0x10D1B]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER NYA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D1B,
+ },
+ [0x10D1C]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA LETTER VA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D1C,
+ },
+ [0x10D1D]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA VOWEL A",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D1D,
+ },
+ [0x10D1E]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA VOWEL I",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D1E,
+ },
+ [0x10D1F]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA VOWEL U",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D1F,
+ },
+ [0x10D20]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA VOWEL E",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D20,
+ },
+ [0x10D21]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA VOWEL O",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D21,
+ },
+ [0x10D22]={
+ arabic="r",
+ category="lo",
+ description="HANIFI ROHINGYA MARK SAKIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D22,
+ },
+ [0x10D23]={
+ arabic="d",
+ category="lo",
+ description="HANIFI ROHINGYA MARK NA KHONNA",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10D23,
+ },
+ [0x10D24]={
+ category="mn",
+ combining=0xE6,
+ description="HANIFI ROHINGYA SIGN HARBAHAY",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10D24,
+ },
+ [0x10D25]={
+ category="mn",
+ combining=0xE6,
+ description="HANIFI ROHINGYA SIGN TAHALA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10D25,
+ },
+ [0x10D26]={
+ category="mn",
+ combining=0xE6,
+ description="HANIFI ROHINGYA SIGN TANA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10D26,
+ },
+ [0x10D27]={
+ category="mn",
+ combining=0xE6,
+ description="HANIFI ROHINGYA SIGN TASSI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10D27,
+ },
+ [0x10D30]={
+ category="nd",
+ description="HANIFI ROHINGYA DIGIT ZERO",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x10D30,
+ },
+ [0x10D31]={
+ category="nd",
+ description="HANIFI ROHINGYA DIGIT ONE",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x10D31,
+ },
+ [0x10D32]={
+ category="nd",
+ description="HANIFI ROHINGYA DIGIT TWO",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x10D32,
+ },
+ [0x10D33]={
+ category="nd",
+ description="HANIFI ROHINGYA DIGIT THREE",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x10D33,
+ },
+ [0x10D34]={
+ category="nd",
+ description="HANIFI ROHINGYA DIGIT FOUR",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x10D34,
+ },
+ [0x10D35]={
+ category="nd",
+ description="HANIFI ROHINGYA DIGIT FIVE",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x10D35,
+ },
+ [0x10D36]={
+ category="nd",
+ description="HANIFI ROHINGYA DIGIT SIX",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x10D36,
+ },
+ [0x10D37]={
+ category="nd",
+ description="HANIFI ROHINGYA DIGIT SEVEN",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x10D37,
+ },
+ [0x10D38]={
+ category="nd",
+ description="HANIFI ROHINGYA DIGIT EIGHT",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x10D38,
+ },
+ [0x10D39]={
+ category="nd",
+ description="HANIFI ROHINGYA DIGIT NINE",
+ direction="an",
+ linebreak="nu",
+ unicodeslot=0x10D39,
+ },
[0x10E60]={
category="no",
description="RUMI DIGIT ONE",
@@ -154535,6 +156079,617 @@ characters.data={
linebreak="al",
unicodeslot=0x10E7E,
},
+ [0x10F00]={
+ category="lo",
+ description="OLD SOGDIAN LETTER ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F00,
+ },
+ [0x10F01]={
+ category="lo",
+ description="OLD SOGDIAN LETTER FINAL ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F01,
+ },
+ [0x10F02]={
+ category="lo",
+ description="OLD SOGDIAN LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F02,
+ },
+ [0x10F03]={
+ category="lo",
+ description="OLD SOGDIAN LETTER FINAL BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F03,
+ },
+ [0x10F04]={
+ category="lo",
+ description="OLD SOGDIAN LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F04,
+ },
+ [0x10F05]={
+ category="lo",
+ description="OLD SOGDIAN LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F05,
+ },
+ [0x10F06]={
+ category="lo",
+ description="OLD SOGDIAN LETTER FINAL HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F06,
+ },
+ [0x10F07]={
+ category="lo",
+ description="OLD SOGDIAN LETTER WAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F07,
+ },
+ [0x10F08]={
+ category="lo",
+ description="OLD SOGDIAN LETTER ZAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F08,
+ },
+ [0x10F09]={
+ category="lo",
+ description="OLD SOGDIAN LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F09,
+ },
+ [0x10F0A]={
+ category="lo",
+ description="OLD SOGDIAN LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F0A,
+ },
+ [0x10F0B]={
+ category="lo",
+ description="OLD SOGDIAN LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F0B,
+ },
+ [0x10F0C]={
+ category="lo",
+ description="OLD SOGDIAN LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F0C,
+ },
+ [0x10F0D]={
+ category="lo",
+ description="OLD SOGDIAN LETTER MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F0D,
+ },
+ [0x10F0E]={
+ category="lo",
+ description="OLD SOGDIAN LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F0E,
+ },
+ [0x10F0F]={
+ category="lo",
+ description="OLD SOGDIAN LETTER FINAL NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F0F,
+ },
+ [0x10F10]={
+ category="lo",
+ description="OLD SOGDIAN LETTER FINAL NUN WITH VERTICAL TAIL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F10,
+ },
+ [0x10F11]={
+ category="lo",
+ description="OLD SOGDIAN LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F11,
+ },
+ [0x10F12]={
+ category="lo",
+ description="OLD SOGDIAN LETTER AYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F12,
+ },
+ [0x10F13]={
+ category="lo",
+ description="OLD SOGDIAN LETTER ALTERNATE AYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F13,
+ },
+ [0x10F14]={
+ category="lo",
+ description="OLD SOGDIAN LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F14,
+ },
+ [0x10F15]={
+ category="lo",
+ description="OLD SOGDIAN LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F15,
+ },
+ [0x10F16]={
+ category="lo",
+ description="OLD SOGDIAN LETTER FINAL SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F16,
+ },
+ [0x10F17]={
+ category="lo",
+ description="OLD SOGDIAN LETTER FINAL SADHE WITH VERTICAL TAIL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F17,
+ },
+ [0x10F18]={
+ category="lo",
+ description="OLD SOGDIAN LETTER RESH-AYIN-DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F18,
+ },
+ [0x10F19]={
+ category="lo",
+ description="OLD SOGDIAN LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F19,
+ },
+ [0x10F1A]={
+ category="lo",
+ description="OLD SOGDIAN LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F1A,
+ },
+ [0x10F1B]={
+ category="lo",
+ description="OLD SOGDIAN LETTER FINAL TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F1B,
+ },
+ [0x10F1C]={
+ category="lo",
+ description="OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F1C,
+ },
+ [0x10F1D]={
+ category="no",
+ description="OLD SOGDIAN NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F1D,
+ },
+ [0x10F1E]={
+ category="no",
+ description="OLD SOGDIAN NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F1E,
+ },
+ [0x10F1F]={
+ category="no",
+ description="OLD SOGDIAN NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F1F,
+ },
+ [0x10F20]={
+ category="no",
+ description="OLD SOGDIAN NUMBER FOUR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F20,
+ },
+ [0x10F21]={
+ category="no",
+ description="OLD SOGDIAN NUMBER FIVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F21,
+ },
+ [0x10F22]={
+ category="no",
+ description="OLD SOGDIAN NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F22,
+ },
+ [0x10F23]={
+ category="no",
+ description="OLD SOGDIAN NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F23,
+ },
+ [0x10F24]={
+ category="no",
+ description="OLD SOGDIAN NUMBER THIRTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F24,
+ },
+ [0x10F25]={
+ category="no",
+ description="OLD SOGDIAN NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F25,
+ },
+ [0x10F26]={
+ category="no",
+ description="OLD SOGDIAN FRACTION ONE HALF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F26,
+ },
+ [0x10F27]={
+ category="lo",
+ description="OLD SOGDIAN LIGATURE AYIN-DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10F27,
+ },
+ [0x10F30]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER ALEPH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F30,
+ },
+ [0x10F31]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER BETH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F31,
+ },
+ [0x10F32]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER GIMEL",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F32,
+ },
+ [0x10F33]={
+ arabic="r",
+ category="lo",
+ description="SOGDIAN LETTER HE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F33,
+ },
+ [0x10F34]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER WAW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F34,
+ },
+ [0x10F35]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER ZAYIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F35,
+ },
+ [0x10F36]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER HETH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F36,
+ },
+ [0x10F37]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER YODH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F37,
+ },
+ [0x10F38]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER KAPH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F38,
+ },
+ [0x10F39]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER LAMEDH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F39,
+ },
+ [0x10F3A]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER MEM",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F3A,
+ },
+ [0x10F3B]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER NUN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F3B,
+ },
+ [0x10F3C]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER SAMEKH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F3C,
+ },
+ [0x10F3D]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER AYIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F3D,
+ },
+ [0x10F3E]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER PE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F3E,
+ },
+ [0x10F3F]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER SADHE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F3F,
+ },
+ [0x10F40]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER RESH-AYIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F40,
+ },
+ [0x10F41]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER SHIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F41,
+ },
+ [0x10F42]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER TAW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F42,
+ },
+ [0x10F43]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER FETH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F43,
+ },
+ [0x10F44]={
+ arabic="d",
+ category="lo",
+ description="SOGDIAN LETTER LESH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F44,
+ },
+ [0x10F45]={
+ arabic="u",
+ category="lo",
+ description="SOGDIAN INDEPENDENT SHIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F45,
+ },
+ [0x10F46]={
+ category="mn",
+ combining=0xDC,
+ description="SOGDIAN COMBINING DOT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10F46,
+ },
+ [0x10F47]={
+ category="mn",
+ combining=0xDC,
+ description="SOGDIAN COMBINING TWO DOTS BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10F47,
+ },
+ [0x10F48]={
+ category="mn",
+ combining=0xE6,
+ description="SOGDIAN COMBINING DOT ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10F48,
+ },
+ [0x10F49]={
+ category="mn",
+ combining=0xE6,
+ description="SOGDIAN COMBINING TWO DOTS ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10F49,
+ },
+ [0x10F4A]={
+ category="mn",
+ combining=0xE6,
+ description="SOGDIAN COMBINING CURVE ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10F4A,
+ },
+ [0x10F4B]={
+ category="mn",
+ combining=0xDC,
+ description="SOGDIAN COMBINING CURVE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10F4B,
+ },
+ [0x10F4C]={
+ category="mn",
+ combining=0xE6,
+ description="SOGDIAN COMBINING HOOK ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10F4C,
+ },
+ [0x10F4D]={
+ category="mn",
+ combining=0xDC,
+ description="SOGDIAN COMBINING HOOK BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10F4D,
+ },
+ [0x10F4E]={
+ category="mn",
+ combining=0xDC,
+ description="SOGDIAN COMBINING LONG HOOK BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10F4E,
+ },
+ [0x10F4F]={
+ category="mn",
+ combining=0xDC,
+ description="SOGDIAN COMBINING RESH BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10F4F,
+ },
+ [0x10F50]={
+ category="mn",
+ combining=0xDC,
+ description="SOGDIAN COMBINING STROKE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x10F50,
+ },
+ [0x10F51]={
+ arabic="d",
+ category="no",
+ description="SOGDIAN NUMBER ONE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F51,
+ },
+ [0x10F52]={
+ arabic="d",
+ category="no",
+ description="SOGDIAN NUMBER TEN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F52,
+ },
+ [0x10F53]={
+ arabic="d",
+ category="no",
+ description="SOGDIAN NUMBER TWENTY",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F53,
+ },
+ [0x10F54]={
+ arabic="r",
+ category="no",
+ description="SOGDIAN NUMBER ONE HUNDRED",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F54,
+ },
+ [0x10F55]={
+ category="po",
+ description="SOGDIAN PUNCTUATION TWO VERTICAL BARS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F55,
+ },
+ [0x10F56]={
+ category="po",
+ description="SOGDIAN PUNCTUATION TWO VERTICAL BARS WITH DOTS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F56,
+ },
+ [0x10F57]={
+ category="po",
+ description="SOGDIAN PUNCTUATION CIRCLE WITH DOT",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F57,
+ },
+ [0x10F58]={
+ category="po",
+ description="SOGDIAN PUNCTUATION TWO CIRCLES WITH DOTS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F58,
+ },
+ [0x10F59]={
+ category="po",
+ description="SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x10F59,
+ },
[0x11000]={
category="mc",
description="BRAHMI SIGN CANDRABINDU",
@@ -155733,6 +157888,7 @@ characters.data={
unicodeslot=0x110BC,
},
[0x110BD]={
+ arabic="u",
category="cf",
description="KAITHI NUMBER SIGN",
direction="l",
@@ -155767,6 +157923,14 @@ characters.data={
linebreak="ba",
unicodeslot=0x110C1,
},
+ [0x110CD]={
+ arabic="u",
+ category="cf",
+ description="KAITHI NUMBER SIGN ABOVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110CD,
+ },
[0x110D0]={
category="lo",
description="SORA SOMPENG LETTER SAH",
@@ -156488,6 +158652,27 @@ characters.data={
linebreak="ba",
unicodeslot=0x11143,
},
+ [0x11144]={
+ category="lo",
+ description="CHAKMA LETTER LHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11144,
+ },
+ [0x11145]={
+ category="mc",
+ description="CHAKMA VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11145,
+ },
+ [0x11146]={
+ category="mc",
+ description="CHAKMA VOWEL SIGN EI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11146,
+ },
[0x11150]={
category="lo",
description="MAHAJANI LETTER A",
@@ -157277,8 +159462,8 @@ characters.data={
[0x111C9]={
category="po",
description="SHARADA SANDHI MARK",
- direction="l",
- linebreak="al",
+ direction="nsm",
+ linebreak="cm",
unicodeslot=0x111C9,
},
[0x111CA]={
@@ -159099,6 +161284,14 @@ characters.data={
linebreak="al",
unicodeslot=0x11339,
},
+ [0x1133B]={
+ category="mn",
+ combining=0x7,
+ description="COMBINING BINDU BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1133B,
+ },
[0x1133C]={
category="mn",
combining=0x7,
@@ -160006,6 +162199,14 @@ characters.data={
linebreak="al",
unicodeslot=0x1145D,
},
+ [0x1145E]={
+ category="mn",
+ combining=0xE6,
+ description="NEWA SANDHI MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1145E,
+ },
[0x11480]={
category="lo",
description="TIRHUTA ANJI",
@@ -162524,6 +164725,13 @@ characters.data={
linebreak="sa",
unicodeslot=0x11719,
},
+ [0x1171A]={
+ category="lo",
+ description="AHOM LETTER ALTERNATE BA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1171A,
+ },
[0x1171D]={
category="mn",
description="AHOM CONSONANT SIGN MEDIAL LA",
@@ -162742,6 +164950,428 @@ characters.data={
linebreak="sa",
unicodeslot=0x1173F,
},
+ [0x11800]={
+ category="lo",
+ description="DOGRA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11800,
+ },
+ [0x11801]={
+ category="lo",
+ description="DOGRA LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11801,
+ },
+ [0x11802]={
+ category="lo",
+ description="DOGRA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11802,
+ },
+ [0x11803]={
+ category="lo",
+ description="DOGRA LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11803,
+ },
+ [0x11804]={
+ category="lo",
+ description="DOGRA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11804,
+ },
+ [0x11805]={
+ category="lo",
+ description="DOGRA LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11805,
+ },
+ [0x11806]={
+ category="lo",
+ description="DOGRA LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11806,
+ },
+ [0x11807]={
+ category="lo",
+ description="DOGRA LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11807,
+ },
+ [0x11808]={
+ category="lo",
+ description="DOGRA LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11808,
+ },
+ [0x11809]={
+ category="lo",
+ description="DOGRA LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11809,
+ },
+ [0x1180A]={
+ category="lo",
+ description="DOGRA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1180A,
+ },
+ [0x1180B]={
+ category="lo",
+ description="DOGRA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1180B,
+ },
+ [0x1180C]={
+ category="lo",
+ description="DOGRA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1180C,
+ },
+ [0x1180D]={
+ category="lo",
+ description="DOGRA LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1180D,
+ },
+ [0x1180E]={
+ category="lo",
+ description="DOGRA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1180E,
+ },
+ [0x1180F]={
+ category="lo",
+ description="DOGRA LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1180F,
+ },
+ [0x11810]={
+ category="lo",
+ description="DOGRA LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11810,
+ },
+ [0x11811]={
+ category="lo",
+ description="DOGRA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11811,
+ },
+ [0x11812]={
+ category="lo",
+ description="DOGRA LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11812,
+ },
+ [0x11813]={
+ category="lo",
+ description="DOGRA LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11813,
+ },
+ [0x11814]={
+ category="lo",
+ description="DOGRA LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11814,
+ },
+ [0x11815]={
+ category="lo",
+ description="DOGRA LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11815,
+ },
+ [0x11816]={
+ category="lo",
+ description="DOGRA LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11816,
+ },
+ [0x11817]={
+ category="lo",
+ description="DOGRA LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11817,
+ },
+ [0x11818]={
+ category="lo",
+ description="DOGRA LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11818,
+ },
+ [0x11819]={
+ category="lo",
+ description="DOGRA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11819,
+ },
+ [0x1181A]={
+ category="lo",
+ description="DOGRA LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1181A,
+ },
+ [0x1181B]={
+ category="lo",
+ description="DOGRA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1181B,
+ },
+ [0x1181C]={
+ category="lo",
+ description="DOGRA LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1181C,
+ },
+ [0x1181D]={
+ category="lo",
+ description="DOGRA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1181D,
+ },
+ [0x1181E]={
+ category="lo",
+ description="DOGRA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1181E,
+ },
+ [0x1181F]={
+ category="lo",
+ description="DOGRA LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1181F,
+ },
+ [0x11820]={
+ category="lo",
+ description="DOGRA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11820,
+ },
+ [0x11821]={
+ category="lo",
+ description="DOGRA LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11821,
+ },
+ [0x11822]={
+ category="lo",
+ description="DOGRA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11822,
+ },
+ [0x11823]={
+ category="lo",
+ description="DOGRA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11823,
+ },
+ [0x11824]={
+ category="lo",
+ description="DOGRA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11824,
+ },
+ [0x11825]={
+ category="lo",
+ description="DOGRA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11825,
+ },
+ [0x11826]={
+ category="lo",
+ description="DOGRA LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11826,
+ },
+ [0x11827]={
+ category="lo",
+ description="DOGRA LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11827,
+ },
+ [0x11828]={
+ category="lo",
+ description="DOGRA LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11828,
+ },
+ [0x11829]={
+ category="lo",
+ description="DOGRA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11829,
+ },
+ [0x1182A]={
+ category="lo",
+ description="DOGRA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1182A,
+ },
+ [0x1182B]={
+ category="lo",
+ description="DOGRA LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1182B,
+ },
+ [0x1182C]={
+ category="mc",
+ description="DOGRA VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1182C,
+ },
+ [0x1182D]={
+ category="mc",
+ description="DOGRA VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1182D,
+ },
+ [0x1182E]={
+ category="mc",
+ description="DOGRA VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1182E,
+ },
+ [0x1182F]={
+ category="mn",
+ description="DOGRA VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1182F,
+ },
+ [0x11830]={
+ category="mn",
+ description="DOGRA VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11830,
+ },
+ [0x11831]={
+ category="mn",
+ description="DOGRA VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11831,
+ },
+ [0x11832]={
+ category="mn",
+ description="DOGRA VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11832,
+ },
+ [0x11833]={
+ category="mn",
+ description="DOGRA VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11833,
+ },
+ [0x11834]={
+ category="mn",
+ description="DOGRA VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11834,
+ },
+ [0x11835]={
+ category="mn",
+ description="DOGRA VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11835,
+ },
+ [0x11836]={
+ category="mn",
+ description="DOGRA VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11836,
+ },
+ [0x11837]={
+ category="mn",
+ description="DOGRA SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11837,
+ },
+ [0x11838]={
+ category="mc",
+ description="DOGRA SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11838,
+ },
+ [0x11839]={
+ category="mn",
+ combining=0x9,
+ description="DOGRA SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11839,
+ },
+ [0x1183A]={
+ category="mn",
+ combining=0x7,
+ description="DOGRA SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1183A,
+ },
+ [0x1183B]={
+ category="po",
+ description="DOGRA ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1183B,
+ },
[0x118A0]={
category="lu",
description="WARANG CITI CAPITAL LETTER NGAA",
@@ -164362,6 +166992,13 @@ characters.data={
linebreak="ba",
unicodeslot=0x11A9C,
},
+ [0x11A9D]={
+ category="lo",
+ description="SOYOMBO MARK PLUTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11A9D,
+ },
[0x11A9E]={
category="po",
description="SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME",
@@ -166480,6 +169117,623 @@ characters.data={
linebreak="nu",
unicodeslot=0x11D59,
},
+ [0x11D60]={
+ category="lo",
+ description="GUNJALA GONDI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D60,
+ },
+ [0x11D61]={
+ category="lo",
+ description="GUNJALA GONDI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D61,
+ },
+ [0x11D62]={
+ category="lo",
+ description="GUNJALA GONDI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D62,
+ },
+ [0x11D63]={
+ category="lo",
+ description="GUNJALA GONDI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D63,
+ },
+ [0x11D64]={
+ category="lo",
+ description="GUNJALA GONDI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D64,
+ },
+ [0x11D65]={
+ category="lo",
+ description="GUNJALA GONDI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D65,
+ },
+ [0x11D67]={
+ category="lo",
+ description="GUNJALA GONDI LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D67,
+ },
+ [0x11D68]={
+ category="lo",
+ description="GUNJALA GONDI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D68,
+ },
+ [0x11D6A]={
+ category="lo",
+ description="GUNJALA GONDI LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D6A,
+ },
+ [0x11D6B]={
+ category="lo",
+ description="GUNJALA GONDI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D6B,
+ },
+ [0x11D6C]={
+ category="lo",
+ description="GUNJALA GONDI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D6C,
+ },
+ [0x11D6D]={
+ category="lo",
+ description="GUNJALA GONDI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D6D,
+ },
+ [0x11D6E]={
+ category="lo",
+ description="GUNJALA GONDI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D6E,
+ },
+ [0x11D6F]={
+ category="lo",
+ description="GUNJALA GONDI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D6F,
+ },
+ [0x11D70]={
+ category="lo",
+ description="GUNJALA GONDI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D70,
+ },
+ [0x11D71]={
+ category="lo",
+ description="GUNJALA GONDI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D71,
+ },
+ [0x11D72]={
+ category="lo",
+ description="GUNJALA GONDI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D72,
+ },
+ [0x11D73]={
+ category="lo",
+ description="GUNJALA GONDI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D73,
+ },
+ [0x11D74]={
+ category="lo",
+ description="GUNJALA GONDI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D74,
+ },
+ [0x11D75]={
+ category="lo",
+ description="GUNJALA GONDI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D75,
+ },
+ [0x11D76]={
+ category="lo",
+ description="GUNJALA GONDI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D76,
+ },
+ [0x11D77]={
+ category="lo",
+ description="GUNJALA GONDI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D77,
+ },
+ [0x11D78]={
+ category="lo",
+ description="GUNJALA GONDI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D78,
+ },
+ [0x11D79]={
+ category="lo",
+ description="GUNJALA GONDI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D79,
+ },
+ [0x11D7A]={
+ category="lo",
+ description="GUNJALA GONDI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D7A,
+ },
+ [0x11D7B]={
+ category="lo",
+ description="GUNJALA GONDI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D7B,
+ },
+ [0x11D7C]={
+ category="lo",
+ description="GUNJALA GONDI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D7C,
+ },
+ [0x11D7D]={
+ category="lo",
+ description="GUNJALA GONDI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D7D,
+ },
+ [0x11D7E]={
+ category="lo",
+ description="GUNJALA GONDI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D7E,
+ },
+ [0x11D7F]={
+ category="lo",
+ description="GUNJALA GONDI LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D7F,
+ },
+ [0x11D80]={
+ category="lo",
+ description="GUNJALA GONDI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D80,
+ },
+ [0x11D81]={
+ category="lo",
+ description="GUNJALA GONDI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D81,
+ },
+ [0x11D82]={
+ category="lo",
+ description="GUNJALA GONDI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D82,
+ },
+ [0x11D83]={
+ category="lo",
+ description="GUNJALA GONDI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D83,
+ },
+ [0x11D84]={
+ category="lo",
+ description="GUNJALA GONDI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D84,
+ },
+ [0x11D85]={
+ category="lo",
+ description="GUNJALA GONDI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D85,
+ },
+ [0x11D86]={
+ category="lo",
+ description="GUNJALA GONDI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D86,
+ },
+ [0x11D87]={
+ category="lo",
+ description="GUNJALA GONDI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D87,
+ },
+ [0x11D88]={
+ category="lo",
+ description="GUNJALA GONDI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D88,
+ },
+ [0x11D89]={
+ category="lo",
+ description="GUNJALA GONDI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D89,
+ },
+ [0x11D8A]={
+ category="mc",
+ description="GUNJALA GONDI VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11D8A,
+ },
+ [0x11D8B]={
+ category="mc",
+ description="GUNJALA GONDI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11D8B,
+ },
+ [0x11D8C]={
+ category="mc",
+ description="GUNJALA GONDI VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11D8C,
+ },
+ [0x11D8D]={
+ category="mc",
+ description="GUNJALA GONDI VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11D8D,
+ },
+ [0x11D8E]={
+ category="mc",
+ description="GUNJALA GONDI VOWEL SIGN UU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11D8E,
+ },
+ [0x11D90]={
+ category="mn",
+ description="GUNJALA GONDI VOWEL SIGN EE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11D90,
+ },
+ [0x11D91]={
+ category="mn",
+ description="GUNJALA GONDI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11D91,
+ },
+ [0x11D93]={
+ category="mc",
+ description="GUNJALA GONDI VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11D93,
+ },
+ [0x11D94]={
+ category="mc",
+ description="GUNJALA GONDI VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11D94,
+ },
+ [0x11D95]={
+ category="mn",
+ description="GUNJALA GONDI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11D95,
+ },
+ [0x11D96]={
+ category="mc",
+ description="GUNJALA GONDI SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11D96,
+ },
+ [0x11D97]={
+ category="mn",
+ combining=0x9,
+ description="GUNJALA GONDI VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11D97,
+ },
+ [0x11D98]={
+ category="lo",
+ description="GUNJALA GONDI OM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11D98,
+ },
+ [0x11DA0]={
+ category="nd",
+ description="GUNJALA GONDI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11DA0,
+ },
+ [0x11DA1]={
+ category="nd",
+ description="GUNJALA GONDI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11DA1,
+ },
+ [0x11DA2]={
+ category="nd",
+ description="GUNJALA GONDI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11DA2,
+ },
+ [0x11DA3]={
+ category="nd",
+ description="GUNJALA GONDI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11DA3,
+ },
+ [0x11DA4]={
+ category="nd",
+ description="GUNJALA GONDI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11DA4,
+ },
+ [0x11DA5]={
+ category="nd",
+ description="GUNJALA GONDI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11DA5,
+ },
+ [0x11DA6]={
+ category="nd",
+ description="GUNJALA GONDI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11DA6,
+ },
+ [0x11DA7]={
+ category="nd",
+ description="GUNJALA GONDI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11DA7,
+ },
+ [0x11DA8]={
+ category="nd",
+ description="GUNJALA GONDI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11DA8,
+ },
+ [0x11DA9]={
+ category="nd",
+ description="GUNJALA GONDI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11DA9,
+ },
+ [0x11EE0]={
+ category="lo",
+ description="MAKASAR LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EE0,
+ },
+ [0x11EE1]={
+ category="lo",
+ description="MAKASAR LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EE1,
+ },
+ [0x11EE2]={
+ category="lo",
+ description="MAKASAR LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EE2,
+ },
+ [0x11EE3]={
+ category="lo",
+ description="MAKASAR LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EE3,
+ },
+ [0x11EE4]={
+ category="lo",
+ description="MAKASAR LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EE4,
+ },
+ [0x11EE5]={
+ category="lo",
+ description="MAKASAR LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EE5,
+ },
+ [0x11EE6]={
+ category="lo",
+ description="MAKASAR LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EE6,
+ },
+ [0x11EE7]={
+ category="lo",
+ description="MAKASAR LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EE7,
+ },
+ [0x11EE8]={
+ category="lo",
+ description="MAKASAR LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EE8,
+ },
+ [0x11EE9]={
+ category="lo",
+ description="MAKASAR LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EE9,
+ },
+ [0x11EEA]={
+ category="lo",
+ description="MAKASAR LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EEA,
+ },
+ [0x11EEB]={
+ category="lo",
+ description="MAKASAR LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EEB,
+ },
+ [0x11EEC]={
+ category="lo",
+ description="MAKASAR LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EEC,
+ },
+ [0x11EED]={
+ category="lo",
+ description="MAKASAR LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EED,
+ },
+ [0x11EEE]={
+ category="lo",
+ description="MAKASAR LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EEE,
+ },
+ [0x11EEF]={
+ category="lo",
+ description="MAKASAR LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EEF,
+ },
+ [0x11EF0]={
+ category="lo",
+ description="MAKASAR LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EF0,
+ },
+ [0x11EF1]={
+ category="lo",
+ description="MAKASAR LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EF1,
+ },
+ [0x11EF2]={
+ category="lo",
+ description="MAKASAR ANGKA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EF2,
+ },
+ [0x11EF3]={
+ category="mn",
+ description="MAKASAR VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11EF3,
+ },
+ [0x11EF4]={
+ category="mn",
+ description="MAKASAR VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11EF4,
+ },
+ [0x11EF5]={
+ category="mc",
+ description="MAKASAR VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11EF5,
+ },
+ [0x11EF6]={
+ category="mc",
+ description="MAKASAR VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11EF6,
+ },
+ [0x11EF7]={
+ category="po",
+ description="MAKASAR PASSIMBANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EF7,
+ },
+ [0x11EF8]={
+ category="po",
+ description="MAKASAR END OF SECTION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11EF8,
+ },
[0x12000]={
category="lo",
description="CUNEIFORM SIGN A",
@@ -192135,6 +195389,643 @@ characters.data={
linebreak="al",
unicodeslot=0x16B8F,
},
+ [0x16E40]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E40,
+ },
+ [0x16E41]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E41,
+ },
+ [0x16E42]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER V",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E42,
+ },
+ [0x16E43]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E43,
+ },
+ [0x16E44]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER ATIU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E44,
+ },
+ [0x16E45]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E45,
+ },
+ [0x16E46]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER KP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E46,
+ },
+ [0x16E47]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E47,
+ },
+ [0x16E48]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E48,
+ },
+ [0x16E49]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E49,
+ },
+ [0x16E4A]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E4A,
+ },
+ [0x16E4B]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E4B,
+ },
+ [0x16E4C]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E4C,
+ },
+ [0x16E4D]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E4D,
+ },
+ [0x16E4E]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E4E,
+ },
+ [0x16E4F]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E4F,
+ },
+ [0x16E50]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E50,
+ },
+ [0x16E51]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E51,
+ },
+ [0x16E52]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E52,
+ },
+ [0x16E53]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E53,
+ },
+ [0x16E54]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E54,
+ },
+ [0x16E55]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER Q",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E55,
+ },
+ [0x16E56]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER HP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E56,
+ },
+ [0x16E57]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER NY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E57,
+ },
+ [0x16E58]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER X",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E58,
+ },
+ [0x16E59]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E59,
+ },
+ [0x16E5A]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E5A,
+ },
+ [0x16E5B]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E5B,
+ },
+ [0x16E5C]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E5C,
+ },
+ [0x16E5D]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E5D,
+ },
+ [0x16E5E]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E5E,
+ },
+ [0x16E5F]={
+ category="lu",
+ description="MEDEFAIDRIN CAPITAL LETTER Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E5F,
+ },
+ [0x16E60]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E60,
+ },
+ [0x16E61]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E61,
+ },
+ [0x16E62]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER V",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E62,
+ },
+ [0x16E63]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E63,
+ },
+ [0x16E64]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER ATIU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E64,
+ },
+ [0x16E65]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E65,
+ },
+ [0x16E66]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER KP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E66,
+ },
+ [0x16E67]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E67,
+ },
+ [0x16E68]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E68,
+ },
+ [0x16E69]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E69,
+ },
+ [0x16E6A]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E6A,
+ },
+ [0x16E6B]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E6B,
+ },
+ [0x16E6C]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E6C,
+ },
+ [0x16E6D]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E6D,
+ },
+ [0x16E6E]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E6E,
+ },
+ [0x16E6F]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E6F,
+ },
+ [0x16E70]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E70,
+ },
+ [0x16E71]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E71,
+ },
+ [0x16E72]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E72,
+ },
+ [0x16E73]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E73,
+ },
+ [0x16E74]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E74,
+ },
+ [0x16E75]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER Q",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E75,
+ },
+ [0x16E76]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER HP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E76,
+ },
+ [0x16E77]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER NY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E77,
+ },
+ [0x16E78]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER X",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E78,
+ },
+ [0x16E79]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E79,
+ },
+ [0x16E7A]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E7A,
+ },
+ [0x16E7B]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E7B,
+ },
+ [0x16E7C]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E7C,
+ },
+ [0x16E7D]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E7D,
+ },
+ [0x16E7E]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E7E,
+ },
+ [0x16E7F]={
+ category="ll",
+ description="MEDEFAIDRIN SMALL LETTER Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E7F,
+ },
+ [0x16E80]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT ZERO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E80,
+ },
+ [0x16E81]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E81,
+ },
+ [0x16E82]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E82,
+ },
+ [0x16E83]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT THREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E83,
+ },
+ [0x16E84]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT FOUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E84,
+ },
+ [0x16E85]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT FIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E85,
+ },
+ [0x16E86]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT SIX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E86,
+ },
+ [0x16E87]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT SEVEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E87,
+ },
+ [0x16E88]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT EIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E88,
+ },
+ [0x16E89]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT NINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E89,
+ },
+ [0x16E8A]={
+ category="no",
+ description="MEDEFAIDRIN NUMBER TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E8A,
+ },
+ [0x16E8B]={
+ category="no",
+ description="MEDEFAIDRIN NUMBER ELEVEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E8B,
+ },
+ [0x16E8C]={
+ category="no",
+ description="MEDEFAIDRIN NUMBER TWELVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E8C,
+ },
+ [0x16E8D]={
+ category="no",
+ description="MEDEFAIDRIN NUMBER THIRTEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E8D,
+ },
+ [0x16E8E]={
+ category="no",
+ description="MEDEFAIDRIN NUMBER FOURTEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E8E,
+ },
+ [0x16E8F]={
+ category="no",
+ description="MEDEFAIDRIN NUMBER FIFTEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E8F,
+ },
+ [0x16E90]={
+ category="no",
+ description="MEDEFAIDRIN NUMBER SIXTEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E90,
+ },
+ [0x16E91]={
+ category="no",
+ description="MEDEFAIDRIN NUMBER SEVENTEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E91,
+ },
+ [0x16E92]={
+ category="no",
+ description="MEDEFAIDRIN NUMBER EIGHTEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E92,
+ },
+ [0x16E93]={
+ category="no",
+ description="MEDEFAIDRIN NUMBER NINETEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E93,
+ },
+ [0x16E94]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT ONE ALTERNATE FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E94,
+ },
+ [0x16E95]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT TWO ALTERNATE FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E95,
+ },
+ [0x16E96]={
+ category="no",
+ description="MEDEFAIDRIN DIGIT THREE ALTERNATE FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E96,
+ },
+ [0x16E97]={
+ category="po",
+ description="MEDEFAIDRIN COMMA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x16E97,
+ },
+ [0x16E98]={
+ category="po",
+ description="MEDEFAIDRIN FULL STOP",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x16E98,
+ },
+ [0x16E99]={
+ category="po",
+ description="MEDEFAIDRIN SYMBOL AIVA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E99,
+ },
+ [0x16E9A]={
+ category="po",
+ description="MEDEFAIDRIN EXCLAMATION OH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16E9A,
+ },
[0x16F00]={
category="lo",
description="MIAO LETTER PA",
@@ -209493,6 +213384,146 @@ characters.data={
linebreak="al",
unicodeslot=0x1D245,
},
+ [0x1D2E0]={
+ category="no",
+ description="MAYAN NUMERAL ZERO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2E0,
+ },
+ [0x1D2E1]={
+ category="no",
+ description="MAYAN NUMERAL ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2E1,
+ },
+ [0x1D2E2]={
+ category="no",
+ description="MAYAN NUMERAL TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2E2,
+ },
+ [0x1D2E3]={
+ category="no",
+ description="MAYAN NUMERAL THREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2E3,
+ },
+ [0x1D2E4]={
+ category="no",
+ description="MAYAN NUMERAL FOUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2E4,
+ },
+ [0x1D2E5]={
+ category="no",
+ description="MAYAN NUMERAL FIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2E5,
+ },
+ [0x1D2E6]={
+ category="no",
+ description="MAYAN NUMERAL SIX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2E6,
+ },
+ [0x1D2E7]={
+ category="no",
+ description="MAYAN NUMERAL SEVEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2E7,
+ },
+ [0x1D2E8]={
+ category="no",
+ description="MAYAN NUMERAL EIGHT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2E8,
+ },
+ [0x1D2E9]={
+ category="no",
+ description="MAYAN NUMERAL NINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2E9,
+ },
+ [0x1D2EA]={
+ category="no",
+ description="MAYAN NUMERAL TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2EA,
+ },
+ [0x1D2EB]={
+ category="no",
+ description="MAYAN NUMERAL ELEVEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2EB,
+ },
+ [0x1D2EC]={
+ category="no",
+ description="MAYAN NUMERAL TWELVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2EC,
+ },
+ [0x1D2ED]={
+ category="no",
+ description="MAYAN NUMERAL THIRTEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2ED,
+ },
+ [0x1D2EE]={
+ category="no",
+ description="MAYAN NUMERAL FOURTEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2EE,
+ },
+ [0x1D2EF]={
+ category="no",
+ description="MAYAN NUMERAL FIFTEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2EF,
+ },
+ [0x1D2F0]={
+ category="no",
+ description="MAYAN NUMERAL SIXTEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2F0,
+ },
+ [0x1D2F1]={
+ category="no",
+ description="MAYAN NUMERAL SEVENTEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2F1,
+ },
+ [0x1D2F2]={
+ category="no",
+ description="MAYAN NUMERAL EIGHTEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2F2,
+ },
+ [0x1D2F3]={
+ category="no",
+ description="MAYAN NUMERAL NINETEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D2F3,
+ },
[0x1D300]={
category="so",
description="MONOGRAM FOR EARTH",
@@ -210228,6 +214259,55 @@ characters.data={
linebreak="al",
unicodeslot=0x1D371,
},
+ [0x1D372]={
+ category="no",
+ description="IDEOGRAPHIC TALLY MARK ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D372,
+ },
+ [0x1D373]={
+ category="no",
+ description="IDEOGRAPHIC TALLY MARK TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D373,
+ },
+ [0x1D374]={
+ category="no",
+ description="IDEOGRAPHIC TALLY MARK THREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D374,
+ },
+ [0x1D375]={
+ category="no",
+ description="IDEOGRAPHIC TALLY MARK FOUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D375,
+ },
+ [0x1D376]={
+ category="no",
+ description="IDEOGRAPHIC TALLY MARK FIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D376,
+ },
+ [0x1D377]={
+ category="no",
+ description="TALLY MARK ONE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D377,
+ },
+ [0x1D378]={
+ category="no",
+ description="TALLY MARK FIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D378,
+ },
[0x1D400]={
category="lu",
description="MATHEMATICAL BOLD CAPITAL A",
@@ -226170,6 +230250,482 @@ characters.data={
linebreak="op",
unicodeslot=0x1E95F,
},
+ [0x1EC71]={
+ category="no",
+ description="INDIC SIYAQ NUMBER ONE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC71,
+ },
+ [0x1EC72]={
+ category="no",
+ description="INDIC SIYAQ NUMBER TWO",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC72,
+ },
+ [0x1EC73]={
+ category="no",
+ description="INDIC SIYAQ NUMBER THREE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC73,
+ },
+ [0x1EC74]={
+ category="no",
+ description="INDIC SIYAQ NUMBER FOUR",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC74,
+ },
+ [0x1EC75]={
+ category="no",
+ description="INDIC SIYAQ NUMBER FIVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC75,
+ },
+ [0x1EC76]={
+ category="no",
+ description="INDIC SIYAQ NUMBER SIX",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC76,
+ },
+ [0x1EC77]={
+ category="no",
+ description="INDIC SIYAQ NUMBER SEVEN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC77,
+ },
+ [0x1EC78]={
+ category="no",
+ description="INDIC SIYAQ NUMBER EIGHT",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC78,
+ },
+ [0x1EC79]={
+ category="no",
+ description="INDIC SIYAQ NUMBER NINE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC79,
+ },
+ [0x1EC7A]={
+ category="no",
+ description="INDIC SIYAQ NUMBER TEN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC7A,
+ },
+ [0x1EC7B]={
+ category="no",
+ description="INDIC SIYAQ NUMBER TWENTY",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC7B,
+ },
+ [0x1EC7C]={
+ category="no",
+ description="INDIC SIYAQ NUMBER THIRTY",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC7C,
+ },
+ [0x1EC7D]={
+ category="no",
+ description="INDIC SIYAQ NUMBER FORTY",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC7D,
+ },
+ [0x1EC7E]={
+ category="no",
+ description="INDIC SIYAQ NUMBER FIFTY",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC7E,
+ },
+ [0x1EC7F]={
+ category="no",
+ description="INDIC SIYAQ NUMBER SIXTY",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC7F,
+ },
+ [0x1EC80]={
+ category="no",
+ description="INDIC SIYAQ NUMBER SEVENTY",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC80,
+ },
+ [0x1EC81]={
+ category="no",
+ description="INDIC SIYAQ NUMBER EIGHTY",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC81,
+ },
+ [0x1EC82]={
+ category="no",
+ description="INDIC SIYAQ NUMBER NINETY",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC82,
+ },
+ [0x1EC83]={
+ category="no",
+ description="INDIC SIYAQ NUMBER ONE HUNDRED",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC83,
+ },
+ [0x1EC84]={
+ category="no",
+ description="INDIC SIYAQ NUMBER TWO HUNDRED",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC84,
+ },
+ [0x1EC85]={
+ category="no",
+ description="INDIC SIYAQ NUMBER THREE HUNDRED",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC85,
+ },
+ [0x1EC86]={
+ category="no",
+ description="INDIC SIYAQ NUMBER FOUR HUNDRED",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC86,
+ },
+ [0x1EC87]={
+ category="no",
+ description="INDIC SIYAQ NUMBER FIVE HUNDRED",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC87,
+ },
+ [0x1EC88]={
+ category="no",
+ description="INDIC SIYAQ NUMBER SIX HUNDRED",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC88,
+ },
+ [0x1EC89]={
+ category="no",
+ description="INDIC SIYAQ NUMBER SEVEN HUNDRED",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC89,
+ },
+ [0x1EC8A]={
+ category="no",
+ description="INDIC SIYAQ NUMBER EIGHT HUNDRED",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC8A,
+ },
+ [0x1EC8B]={
+ category="no",
+ description="INDIC SIYAQ NUMBER NINE HUNDRED",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC8B,
+ },
+ [0x1EC8C]={
+ category="no",
+ description="INDIC SIYAQ NUMBER ONE THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC8C,
+ },
+ [0x1EC8D]={
+ category="no",
+ description="INDIC SIYAQ NUMBER TWO THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC8D,
+ },
+ [0x1EC8E]={
+ category="no",
+ description="INDIC SIYAQ NUMBER THREE THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC8E,
+ },
+ [0x1EC8F]={
+ category="no",
+ description="INDIC SIYAQ NUMBER FOUR THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC8F,
+ },
+ [0x1EC90]={
+ category="no",
+ description="INDIC SIYAQ NUMBER FIVE THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC90,
+ },
+ [0x1EC91]={
+ category="no",
+ description="INDIC SIYAQ NUMBER SIX THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC91,
+ },
+ [0x1EC92]={
+ category="no",
+ description="INDIC SIYAQ NUMBER SEVEN THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC92,
+ },
+ [0x1EC93]={
+ category="no",
+ description="INDIC SIYAQ NUMBER EIGHT THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC93,
+ },
+ [0x1EC94]={
+ category="no",
+ description="INDIC SIYAQ NUMBER NINE THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC94,
+ },
+ [0x1EC95]={
+ category="no",
+ description="INDIC SIYAQ NUMBER TEN THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC95,
+ },
+ [0x1EC96]={
+ category="no",
+ description="INDIC SIYAQ NUMBER TWENTY THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC96,
+ },
+ [0x1EC97]={
+ category="no",
+ description="INDIC SIYAQ NUMBER THIRTY THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC97,
+ },
+ [0x1EC98]={
+ category="no",
+ description="INDIC SIYAQ NUMBER FORTY THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC98,
+ },
+ [0x1EC99]={
+ category="no",
+ description="INDIC SIYAQ NUMBER FIFTY THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC99,
+ },
+ [0x1EC9A]={
+ category="no",
+ description="INDIC SIYAQ NUMBER SIXTY THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC9A,
+ },
+ [0x1EC9B]={
+ category="no",
+ description="INDIC SIYAQ NUMBER SEVENTY THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC9B,
+ },
+ [0x1EC9C]={
+ category="no",
+ description="INDIC SIYAQ NUMBER EIGHTY THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC9C,
+ },
+ [0x1EC9D]={
+ category="no",
+ description="INDIC SIYAQ NUMBER NINETY THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC9D,
+ },
+ [0x1EC9E]={
+ category="no",
+ description="INDIC SIYAQ NUMBER LAKH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC9E,
+ },
+ [0x1EC9F]={
+ category="no",
+ description="INDIC SIYAQ NUMBER LAKHAN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1EC9F,
+ },
+ [0x1ECA0]={
+ category="no",
+ description="INDIC SIYAQ LAKH MARK",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECA0,
+ },
+ [0x1ECA1]={
+ category="no",
+ description="INDIC SIYAQ NUMBER KAROR",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECA1,
+ },
+ [0x1ECA2]={
+ category="no",
+ description="INDIC SIYAQ NUMBER KARORAN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECA2,
+ },
+ [0x1ECA3]={
+ category="no",
+ description="INDIC SIYAQ NUMBER PREFIXED ONE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECA3,
+ },
+ [0x1ECA4]={
+ category="no",
+ description="INDIC SIYAQ NUMBER PREFIXED TWO",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECA4,
+ },
+ [0x1ECA5]={
+ category="no",
+ description="INDIC SIYAQ NUMBER PREFIXED THREE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECA5,
+ },
+ [0x1ECA6]={
+ category="no",
+ description="INDIC SIYAQ NUMBER PREFIXED FOUR",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECA6,
+ },
+ [0x1ECA7]={
+ category="no",
+ description="INDIC SIYAQ NUMBER PREFIXED FIVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECA7,
+ },
+ [0x1ECA8]={
+ category="no",
+ description="INDIC SIYAQ NUMBER PREFIXED SIX",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECA8,
+ },
+ [0x1ECA9]={
+ category="no",
+ description="INDIC SIYAQ NUMBER PREFIXED SEVEN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECA9,
+ },
+ [0x1ECAA]={
+ category="no",
+ description="INDIC SIYAQ NUMBER PREFIXED EIGHT",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECAA,
+ },
+ [0x1ECAB]={
+ category="no",
+ description="INDIC SIYAQ NUMBER PREFIXED NINE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECAB,
+ },
+ [0x1ECAC]={
+ category="so",
+ description="INDIC SIYAQ PLACEHOLDER",
+ direction="al",
+ linebreak="po",
+ unicodeslot=0x1ECAC,
+ },
+ [0x1ECAD]={
+ category="no",
+ description="INDIC SIYAQ FRACTION ONE QUARTER",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECAD,
+ },
+ [0x1ECAE]={
+ category="no",
+ description="INDIC SIYAQ FRACTION ONE HALF",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECAE,
+ },
+ [0x1ECAF]={
+ category="no",
+ description="INDIC SIYAQ FRACTION THREE QUARTERS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECAF,
+ },
+ [0x1ECB0]={
+ category="sc",
+ description="INDIC SIYAQ RUPEE MARK",
+ direction="al",
+ linebreak="po",
+ unicodeslot=0x1ECB0,
+ },
+ [0x1ECB1]={
+ category="no",
+ description="INDIC SIYAQ NUMBER ALTERNATE ONE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECB1,
+ },
+ [0x1ECB2]={
+ category="no",
+ description="INDIC SIYAQ NUMBER ALTERNATE TWO",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECB2,
+ },
+ [0x1ECB3]={
+ category="no",
+ description="INDIC SIYAQ NUMBER ALTERNATE TEN THOUSAND",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECB3,
+ },
+ [0x1ECB4]={
+ category="no",
+ description="INDIC SIYAQ ALTERNATE LAKH MARK",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x1ECB4,
+ },
[0x1EE00]={
category="lo",
comment="check math properties",
@@ -229431,6 +233987,13 @@ characters.data={
specials={ "circle", 0x57, 0x5A },
unicodeslot=0x1F12E,
},
+ [0x1F12F]={
+ category="so",
+ description="COPYLEFT SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F12F,
+ },
[0x1F130]={
category="so",
cjkwd="a",
@@ -239053,6 +243616,14 @@ characters.data={
linebreak="id",
unicodeslot=0x1F6F8,
},
+ [0x1F6F9]={
+ category="so",
+ cjkwd="w",
+ description="SKATEBOARD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F6F9,
+ },
[0x1F700]={
category="so",
description="ALCHEMICAL SYMBOL FOR QUINTESSENCE",
@@ -240461,6 +245032,34 @@ characters.data={
linebreak="al",
unicodeslot=0x1F7D4,
},
+ [0x1F7D5]={
+ category="so",
+ description="CIRCLED TRIANGLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F7D5,
+ },
+ [0x1F7D6]={
+ category="so",
+ description="NEGATIVE CIRCLED TRIANGLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F7D6,
+ },
+ [0x1F7D7]={
+ category="so",
+ description="CIRCLED SQUARE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F7D7,
+ },
+ [0x1F7D8]={
+ category="so",
+ description="NEGATIVE CIRCLED SQUARE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F7D8,
+ },
[0x1F800]={
category="so",
description="LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD",
@@ -242067,6 +246666,30 @@ characters.data={
linebreak="id",
unicodeslot=0x1F94C,
},
+ [0x1F94D]={
+ category="so",
+ cjkwd="w",
+ description="LACROSSE STICK AND BALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F94D,
+ },
+ [0x1F94E]={
+ category="so",
+ cjkwd="w",
+ description="SOFTBALL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F94E,
+ },
+ [0x1F94F]={
+ category="so",
+ cjkwd="w",
+ description="FLYING DISC",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F94F,
+ },
[0x1F950]={
category="so",
cjkwd="w",
@@ -242292,6 +246915,118 @@ characters.data={
linebreak="id",
unicodeslot=0x1F96B,
},
+ [0x1F96C]={
+ category="so",
+ cjkwd="w",
+ description="LEAFY GREEN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F96C,
+ },
+ [0x1F96D]={
+ category="so",
+ cjkwd="w",
+ description="MANGO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F96D,
+ },
+ [0x1F96E]={
+ category="so",
+ cjkwd="w",
+ description="MOON CAKE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F96E,
+ },
+ [0x1F96F]={
+ category="so",
+ cjkwd="w",
+ description="BAGEL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F96F,
+ },
+ [0x1F970]={
+ category="so",
+ cjkwd="w",
+ description="SMILING FACE WITH SMILING EYES AND THREE HEARTS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F970,
+ },
+ [0x1F973]={
+ category="so",
+ cjkwd="w",
+ description="FACE WITH PARTY HORN AND PARTY HAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F973,
+ },
+ [0x1F974]={
+ category="so",
+ cjkwd="w",
+ description="FACE WITH UNEVEN EYES AND WAVY MOUTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F974,
+ },
+ [0x1F975]={
+ category="so",
+ cjkwd="w",
+ description="OVERHEATED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F975,
+ },
+ [0x1F976]={
+ category="so",
+ cjkwd="w",
+ description="FREEZING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F976,
+ },
+ [0x1F97A]={
+ category="so",
+ cjkwd="w",
+ description="FACE WITH PLEADING EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F97A,
+ },
+ [0x1F97C]={
+ category="so",
+ cjkwd="w",
+ description="LAB COAT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F97C,
+ },
+ [0x1F97D]={
+ category="so",
+ cjkwd="w",
+ description="GOGGLES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F97D,
+ },
+ [0x1F97E]={
+ category="so",
+ cjkwd="w",
+ description="HIKING BOOT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F97E,
+ },
+ [0x1F97F]={
+ category="so",
+ cjkwd="w",
+ description="FLAT SHOE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F97F,
+ },
[0x1F980]={
category="so",
cjkwd="w",
@@ -242485,6 +247220,174 @@ characters.data={
linebreak="id",
unicodeslot=0x1F997,
},
+ [0x1F998]={
+ category="so",
+ cjkwd="w",
+ description="KANGAROO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F998,
+ },
+ [0x1F999]={
+ category="so",
+ cjkwd="w",
+ description="LLAMA",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F999,
+ },
+ [0x1F99A]={
+ category="so",
+ cjkwd="w",
+ description="PEACOCK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F99A,
+ },
+ [0x1F99B]={
+ category="so",
+ cjkwd="w",
+ description="HIPPOPOTAMUS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F99B,
+ },
+ [0x1F99C]={
+ category="so",
+ cjkwd="w",
+ description="PARROT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F99C,
+ },
+ [0x1F99D]={
+ category="so",
+ cjkwd="w",
+ description="RACCOON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F99D,
+ },
+ [0x1F99E]={
+ category="so",
+ cjkwd="w",
+ description="LOBSTER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F99E,
+ },
+ [0x1F99F]={
+ category="so",
+ cjkwd="w",
+ description="MOSQUITO",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F99F,
+ },
+ [0x1F9A0]={
+ category="so",
+ cjkwd="w",
+ description="MICROBE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9A0,
+ },
+ [0x1F9A1]={
+ category="so",
+ cjkwd="w",
+ description="BADGER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9A1,
+ },
+ [0x1F9A2]={
+ category="so",
+ cjkwd="w",
+ description="SWAN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9A2,
+ },
+ [0x1F9B0]={
+ category="so",
+ cjkwd="w",
+ description="EMOJI COMPONENT RED HAIR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9B0,
+ },
+ [0x1F9B1]={
+ category="so",
+ cjkwd="w",
+ description="EMOJI COMPONENT CURLY HAIR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9B1,
+ },
+ [0x1F9B2]={
+ category="so",
+ cjkwd="w",
+ description="EMOJI COMPONENT BALD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9B2,
+ },
+ [0x1F9B3]={
+ category="so",
+ cjkwd="w",
+ description="EMOJI COMPONENT WHITE HAIR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9B3,
+ },
+ [0x1F9B4]={
+ category="so",
+ cjkwd="w",
+ description="BONE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9B4,
+ },
+ [0x1F9B5]={
+ category="so",
+ cjkwd="w",
+ description="LEG",
+ direction="on",
+ linebreak="eb",
+ unicodeslot=0x1F9B5,
+ },
+ [0x1F9B6]={
+ category="so",
+ cjkwd="w",
+ description="FOOT",
+ direction="on",
+ linebreak="eb",
+ unicodeslot=0x1F9B6,
+ },
+ [0x1F9B7]={
+ category="so",
+ cjkwd="w",
+ description="TOOTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9B7,
+ },
+ [0x1F9B8]={
+ category="so",
+ cjkwd="w",
+ description="SUPERHERO",
+ direction="on",
+ linebreak="eb",
+ unicodeslot=0x1F9B8,
+ },
+ [0x1F9B9]={
+ category="so",
+ cjkwd="w",
+ description="SUPERVILLAIN",
+ direction="on",
+ linebreak="eb",
+ unicodeslot=0x1F9B9,
+ },
[0x1F9C0]={
category="so",
cjkwd="w",
@@ -242493,6 +247396,22 @@ characters.data={
linebreak="id",
unicodeslot=0x1F9C0,
},
+ [0x1F9C1]={
+ category="so",
+ cjkwd="w",
+ description="CUPCAKE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9C1,
+ },
+ [0x1F9C2]={
+ category="so",
+ cjkwd="w",
+ description="SALT SHAKER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9C2,
+ },
[0x1F9D0]={
category="so",
cjkwd="w",
@@ -242677,6 +247596,304 @@ characters.data={
linebreak="id",
unicodeslot=0x1F9E6,
},
+ [0x1F9E7]={
+ category="so",
+ cjkwd="w",
+ description="RED GIFT ENVELOPE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9E7,
+ },
+ [0x1F9E8]={
+ category="so",
+ cjkwd="w",
+ description="FIRECRACKER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9E8,
+ },
+ [0x1F9E9]={
+ category="so",
+ cjkwd="w",
+ description="JIGSAW PUZZLE PIECE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9E9,
+ },
+ [0x1F9EA]={
+ category="so",
+ cjkwd="w",
+ description="TEST TUBE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9EA,
+ },
+ [0x1F9EB]={
+ category="so",
+ cjkwd="w",
+ description="PETRI DISH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9EB,
+ },
+ [0x1F9EC]={
+ category="so",
+ cjkwd="w",
+ description="DNA DOUBLE HELIX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9EC,
+ },
+ [0x1F9ED]={
+ category="so",
+ cjkwd="w",
+ description="COMPASS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9ED,
+ },
+ [0x1F9EE]={
+ category="so",
+ cjkwd="w",
+ description="ABACUS",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9EE,
+ },
+ [0x1F9EF]={
+ category="so",
+ cjkwd="w",
+ description="FIRE EXTINGUISHER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9EF,
+ },
+ [0x1F9F0]={
+ category="so",
+ cjkwd="w",
+ description="TOOLBOX",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9F0,
+ },
+ [0x1F9F1]={
+ category="so",
+ cjkwd="w",
+ description="BRICK",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9F1,
+ },
+ [0x1F9F2]={
+ category="so",
+ cjkwd="w",
+ description="MAGNET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9F2,
+ },
+ [0x1F9F3]={
+ category="so",
+ cjkwd="w",
+ description="LUGGAGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9F3,
+ },
+ [0x1F9F4]={
+ category="so",
+ cjkwd="w",
+ description="LOTION BOTTLE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9F4,
+ },
+ [0x1F9F5]={
+ category="so",
+ cjkwd="w",
+ description="SPOOL OF THREAD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9F5,
+ },
+ [0x1F9F6]={
+ category="so",
+ cjkwd="w",
+ description="BALL OF YARN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9F6,
+ },
+ [0x1F9F7]={
+ category="so",
+ cjkwd="w",
+ description="SAFETY PIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9F7,
+ },
+ [0x1F9F8]={
+ category="so",
+ cjkwd="w",
+ description="TEDDY BEAR",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9F8,
+ },
+ [0x1F9F9]={
+ category="so",
+ cjkwd="w",
+ description="BROOM",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9F9,
+ },
+ [0x1F9FA]={
+ category="so",
+ cjkwd="w",
+ description="BASKET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9FA,
+ },
+ [0x1F9FB]={
+ category="so",
+ cjkwd="w",
+ description="ROLL OF PAPER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9FB,
+ },
+ [0x1F9FC]={
+ category="so",
+ cjkwd="w",
+ description="BAR OF SOAP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9FC,
+ },
+ [0x1F9FD]={
+ category="so",
+ cjkwd="w",
+ description="SPONGE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9FD,
+ },
+ [0x1F9FE]={
+ category="so",
+ cjkwd="w",
+ description="RECEIPT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9FE,
+ },
+ [0x1F9FF]={
+ category="so",
+ cjkwd="w",
+ description="NAZAR AMULET",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F9FF,
+ },
+ [0x1FA60]={
+ category="so",
+ description="XIANGQI RED GENERAL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA60,
+ },
+ [0x1FA61]={
+ category="so",
+ description="XIANGQI RED MANDARIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA61,
+ },
+ [0x1FA62]={
+ category="so",
+ description="XIANGQI RED ELEPHANT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA62,
+ },
+ [0x1FA63]={
+ category="so",
+ description="XIANGQI RED HORSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA63,
+ },
+ [0x1FA64]={
+ category="so",
+ description="XIANGQI RED CHARIOT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA64,
+ },
+ [0x1FA65]={
+ category="so",
+ description="XIANGQI RED CANNON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA65,
+ },
+ [0x1FA66]={
+ category="so",
+ description="XIANGQI RED SOLDIER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA66,
+ },
+ [0x1FA67]={
+ category="so",
+ description="XIANGQI BLACK GENERAL",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA67,
+ },
+ [0x1FA68]={
+ category="so",
+ description="XIANGQI BLACK MANDARIN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA68,
+ },
+ [0x1FA69]={
+ category="so",
+ description="XIANGQI BLACK ELEPHANT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA69,
+ },
+ [0x1FA6A]={
+ category="so",
+ description="XIANGQI BLACK HORSE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA6A,
+ },
+ [0x1FA6B]={
+ category="so",
+ description="XIANGQI BLACK CHARIOT",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA6B,
+ },
+ [0x1FA6C]={
+ category="so",
+ description="XIANGQI BLACK CANNON",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA6C,
+ },
+ [0x1FA6D]={
+ category="so",
+ description="XIANGQI BLACK SOLDIER",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1FA6D,
+ },
[0x2F800]={
category="lo",
cjkwd="w",
diff --git a/tex/context/base/mkiv/char-emj.lua b/tex/context/base/mkiv/char-emj.lua
index 718d3bc6e..b00e9ebf8 100644
--- a/tex/context/base/mkiv/char-emj.lua
+++ b/tex/context/base/mkiv/char-emj.lua
@@ -13,60 +13,42 @@ return {
["1st place medal"]={ 0x1F947 },
["2nd place medal"]={ 0x1F948 },
["3rd place medal"]={ 0x1F949 },
- ["a button (blood type)"]={ 0x1F170 },
+ ["a button (blood type)"]={ 0x1F170, 0xFE0F },
["ab button (blood type)"]={ 0x1F18E },
- ["admission tickets"]={ 0x1F39F },
- ["adult"]={ 0x1F9D1 },
- ["adult: dark skin tone"]={ 0x1F9D1, 0x1F3FF },
- ["adult: light skin tone"]={ 0x1F9D1, 0x1F3FB },
- ["adult: medium skin tone"]={ 0x1F9D1, 0x1F3FD },
- ["adult: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE },
- ["adult: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC },
+ ["abacus"]={ 0x1F9EE },
+ ["adhesive bandage"]={ 0x1FA79 },
+ ["admission tickets"]={ 0x1F39F, 0xFE0F },
["aerial tramway"]={ 0x1F6A1 },
- ["afghanistan"]={ 0x1F1E6, 0x1F1EB },
- ["airplane"]={ 0x2708 },
+ ["airplane"]={ 0x2708, 0xFE0F },
["airplane arrival"]={ 0x1F6EC },
["airplane departure"]={ 0x1F6EB },
["alarm clock"]={ 0x23F0 },
- ["albania"]={ 0x1F1E6, 0x1F1F1 },
- ["alembic"]={ 0x2697 },
- ["algeria"]={ 0x1F1E9, 0x1F1FF },
+ ["alembic"]={ 0x2697, 0xFE0F },
["alien"]={ 0x1F47D },
["alien monster"]={ 0x1F47E },
["ambulance"]={ 0x1F691 },
["american football"]={ 0x1F3C8 },
- ["american samoa"]={ 0x1F1E6, 0x1F1F8 },
["amphora"]={ 0x1F3FA },
["anchor"]={ 0x2693 },
- ["andorra"]={ 0x1F1E6, 0x1F1E9 },
["anger symbol"]={ 0x1F4A2 },
- ["angola"]={ 0x1F1E6, 0x1F1F4 },
["angry face"]={ 0x1F620 },
["angry face with horns"]={ 0x1F47F },
- ["anguilla"]={ 0x1F1E6, 0x1F1EE },
["anguished face"]={ 0x1F627 },
["ant"]={ 0x1F41C },
- ["antarctica"]={ 0x1F1E6, 0x1F1F6 },
["antenna bars"]={ 0x1F4F6 },
- ["anticlockwise arrows button"]={ 0x1F504 },
- ["antigua & barbuda"]={ 0x1F1E6, 0x1F1EC },
+ ["anxious face with sweat"]={ 0x1F630 },
["aquarius"]={ 0x2652 },
- ["argentina"]={ 0x1F1E6, 0x1F1F7 },
["aries"]={ 0x2648 },
- ["armenia"]={ 0x1F1E6, 0x1F1F2 },
["articulated lorry"]={ 0x1F69B },
["artist palette"]={ 0x1F3A8 },
- ["aruba"]={ 0x1F1E6, 0x1F1FC },
- ["ascension island"]={ 0x1F1E6, 0x1F1E8 },
["astonished face"]={ 0x1F632 },
["atm sign"]={ 0x1F3E7 },
- ["atom symbol"]={ 0x269B },
- ["australia"]={ 0x1F1E6, 0x1F1FA },
- ["austria"]={ 0x1F1E6, 0x1F1F9 },
+ ["atom symbol"]={ 0x269B, 0xFE0F },
+ ["auto rickshaw"]={ 0x1F6FA },
["automobile"]={ 0x1F697 },
["avocado"]={ 0x1F951 },
- ["azerbaijan"]={ 0x1F1E6, 0x1F1FF },
- ["b button (blood type)"]={ 0x1F171 },
+ ["axe"]={ 0x1FA93 },
+ ["b button (blood type)"]={ 0x1F171, 0xFE0F },
["baby"]={ 0x1F476 },
["baby angel"]={ 0x1F47C },
["baby angel: dark skin tone"]={ 0x1F47C, 0x1F3FF },
@@ -107,97 +89,68 @@ return {
["backhand index pointing up: medium skin tone"]={ 0x1F446, 0x1F3FD },
["backhand index pointing up: medium-dark skin tone"]={ 0x1F446, 0x1F3FE },
["backhand index pointing up: medium-light skin tone"]={ 0x1F446, 0x1F3FC },
+ ["backpack"]={ 0x1F392 },
["bacon"]={ 0x1F953 },
+ ["badger"]={ 0x1F9A1 },
["badminton"]={ 0x1F3F8 },
+ ["bagel"]={ 0x1F96F },
["baggage claim"]={ 0x1F6C4 },
["baguette bread"]={ 0x1F956 },
- ["bahamas"]={ 0x1F1E7, 0x1F1F8 },
- ["bahrain"]={ 0x1F1E7, 0x1F1ED },
- ["balance scale"]={ 0x2696 },
+ ["balance scale"]={ 0x2696, 0xFE0F },
+ ["ballet shoes"]={ 0x1FA70 },
["balloon"]={ 0x1F388 },
- ["ballot box with ballot"]={ 0x1F5F3 },
- ["ballot box with check"]={ 0x2611 },
+ ["ballot box with ballot"]={ 0x1F5F3, 0xFE0F },
["banana"]={ 0x1F34C },
- ["bangladesh"]={ 0x1F1E7, 0x1F1E9 },
+ ["banjo"]={ 0x1FA95 },
["bank"]={ 0x1F3E6 },
["bar chart"]={ 0x1F4CA },
- ["barbados"]={ 0x1F1E7, 0x1F1E7 },
["barber pole"]={ 0x1F488 },
["baseball"]={ 0x26BE },
+ ["basket"]={ 0x1F9FA },
["basketball"]={ 0x1F3C0 },
["bat"]={ 0x1F987 },
["bathtub"]={ 0x1F6C1 },
["battery"]={ 0x1F50B },
- ["beach with umbrella"]={ 0x1F3D6 },
- ["bear face"]={ 0x1F43B },
- ["bearded person"]={ 0x1F9D4 },
- ["bearded person: dark skin tone"]={ 0x1F9D4, 0x1F3FF },
- ["bearded person: light skin tone"]={ 0x1F9D4, 0x1F3FB },
- ["bearded person: medium skin tone"]={ 0x1F9D4, 0x1F3FD },
- ["bearded person: medium-dark skin tone"]={ 0x1F9D4, 0x1F3FE },
- ["bearded person: medium-light skin tone"]={ 0x1F9D4, 0x1F3FC },
+ ["beach with umbrella"]={ 0x1F3D6, 0xFE0F },
+ ["beaming face with smiling eyes"]={ 0x1F601 },
+ ["bear"]={ 0x1F43B },
["beating heart"]={ 0x1F493 },
- ["bed"]={ 0x1F6CF },
+ ["bed"]={ 0x1F6CF, 0xFE0F },
["beer mug"]={ 0x1F37A },
- ["belarus"]={ 0x1F1E7, 0x1F1FE },
- ["belgium"]={ 0x1F1E7, 0x1F1EA },
- ["belize"]={ 0x1F1E7, 0x1F1FF },
["bell"]={ 0x1F514 },
["bell with slash"]={ 0x1F515 },
- ["bellhop bell"]={ 0x1F6CE },
- ["benin"]={ 0x1F1E7, 0x1F1EF },
+ ["bellhop bell"]={ 0x1F6CE, 0xFE0F },
["bento box"]={ 0x1F371 },
- ["bermuda"]={ 0x1F1E7, 0x1F1F2 },
- ["bhutan"]={ 0x1F1E7, 0x1F1F9 },
+ ["beverage box"]={ 0x1F9C3 },
["bicycle"]={ 0x1F6B2 },
["bikini"]={ 0x1F459 },
["billed cap"]={ 0x1F9E2 },
- ["biohazard"]={ 0x2623 },
+ ["biohazard"]={ 0x2623, 0xFE0F },
["bird"]={ 0x1F426 },
["birthday cake"]={ 0x1F382 },
["black circle"]={ 0x26AB },
["black flag"]={ 0x1F3F4 },
["black heart"]={ 0x1F5A4 },
["black large square"]={ 0x2B1B },
- ["black medium square"]={ 0x25FC },
+ ["black medium square"]={ 0x25FC, 0xFE0F },
["black medium-small square"]={ 0x25FE },
- ["black nib"]={ 0x2712 },
- ["black small square"]={ 0x25AA },
+ ["black nib"]={ 0x2712, 0xFE0F },
+ ["black small square"]={ 0x25AA, 0xFE0F },
["black square button"]={ 0x1F532 },
- ["blond-haired man"]={ 0x1F471, 0x200D, 0x2642 },
- ["blond-haired man: dark skin tone"]={ 0x1F471, 0x1F3FF, 0x200D, 0x2642 },
- ["blond-haired man: light skin tone"]={ 0x1F471, 0x1F3FB, 0x200D, 0x2642 },
- ["blond-haired man: medium skin tone"]={ 0x1F471, 0x1F3FD, 0x200D, 0x2642 },
- ["blond-haired man: medium-dark skin tone"]={ 0x1F471, 0x1F3FE, 0x200D, 0x2642 },
- ["blond-haired man: medium-light skin tone"]={ 0x1F471, 0x1F3FC, 0x200D, 0x2642 },
- ["blond-haired person"]={ 0x1F471 },
- ["blond-haired person: dark skin tone"]={ 0x1F471, 0x1F3FF },
- ["blond-haired person: light skin tone"]={ 0x1F471, 0x1F3FB },
- ["blond-haired person: medium skin tone"]={ 0x1F471, 0x1F3FD },
- ["blond-haired person: medium-dark skin tone"]={ 0x1F471, 0x1F3FE },
- ["blond-haired person: medium-light skin tone"]={ 0x1F471, 0x1F3FC },
- ["blond-haired woman"]={ 0x1F471, 0x200D, 0x2640 },
- ["blond-haired woman: dark skin tone"]={ 0x1F471, 0x1F3FF, 0x200D, 0x2640 },
- ["blond-haired woman: light skin tone"]={ 0x1F471, 0x1F3FB, 0x200D, 0x2640 },
- ["blond-haired woman: medium skin tone"]={ 0x1F471, 0x1F3FD, 0x200D, 0x2640 },
- ["blond-haired woman: medium-dark skin tone"]={ 0x1F471, 0x1F3FE, 0x200D, 0x2640 },
- ["blond-haired woman: medium-light skin tone"]={ 0x1F471, 0x1F3FC, 0x200D, 0x2640 },
["blossom"]={ 0x1F33C },
["blowfish"]={ 0x1F421 },
["blue book"]={ 0x1F4D8 },
["blue circle"]={ 0x1F535 },
["blue heart"]={ 0x1F499 },
+ ["blue square"]={ 0x1F7E6 },
["boar"]={ 0x1F417 },
- ["bolivia"]={ 0x1F1E7, 0x1F1F4 },
["bomb"]={ 0x1F4A3 },
+ ["bone"]={ 0x1F9B4 },
["bookmark"]={ 0x1F516 },
["bookmark tabs"]={ 0x1F4D1 },
["books"]={ 0x1F4DA },
- ["bosnia & herzegovina"]={ 0x1F1E7, 0x1F1E6 },
- ["botswana"]={ 0x1F1E7, 0x1F1FC },
["bottle with popping cork"]={ 0x1F37E },
["bouquet"]={ 0x1F490 },
- ["bouvet island"]={ 0x1F1E7, 0x1F1FB },
["bow and arrow"]={ 0x1F3F9 },
["bowl with spoon"]={ 0x1F963 },
["bowling"]={ 0x1F3B3 },
@@ -209,7 +162,6 @@ return {
["boy: medium-dark skin tone"]={ 0x1F466, 0x1F3FE },
["boy: medium-light skin tone"]={ 0x1F466, 0x1F3FC },
["brain"]={ 0x1F9E0 },
- ["brazil"]={ 0x1F1E7, 0x1F1F7 },
["bread"]={ 0x1F35E },
["breast-feeding"]={ 0x1F931 },
["breast-feeding: dark skin tone"]={ 0x1F931, 0x1F3FF },
@@ -217,6 +169,7 @@ return {
["breast-feeding: medium skin tone"]={ 0x1F931, 0x1F3FD },
["breast-feeding: medium-dark skin tone"]={ 0x1F931, 0x1F3FE },
["breast-feeding: medium-light skin tone"]={ 0x1F931, 0x1F3FC },
+ ["brick"]={ 0x1F9F1 },
["bride with veil"]={ 0x1F470 },
["bride with veil: dark skin tone"]={ 0x1F470, 0x1F3FF },
["bride with veil: light skin tone"]={ 0x1F470, 0x1F3FB },
@@ -226,21 +179,21 @@ return {
["bridge at night"]={ 0x1F309 },
["briefcase"]={ 0x1F4BC },
["bright button"]={ 0x1F506 },
- ["british indian ocean territory"]={ 0x1F1EE, 0x1F1F4 },
- ["british virgin islands"]={ 0x1F1FB, 0x1F1EC },
["broccoli"]={ 0x1F966 },
["broken heart"]={ 0x1F494 },
- ["brunei"]={ 0x1F1E7, 0x1F1F3 },
+ ["broom"]={ 0x1F9F9 },
+ ["brown circle"]={ 0x1F7E4 },
+ ["brown heart"]={ 0x1F90E },
+ ["brown square"]={ 0x1F7EB },
["bug"]={ 0x1F41B },
- ["building construction"]={ 0x1F3D7 },
- ["bulgaria"]={ 0x1F1E7, 0x1F1EC },
- ["burkina faso"]={ 0x1F1E7, 0x1F1EB },
+ ["building construction"]={ 0x1F3D7, 0xFE0F },
+ ["bullet train"]={ 0x1F685 },
["burrito"]={ 0x1F32F },
- ["burundi"]={ 0x1F1E7, 0x1F1EE },
["bus"]={ 0x1F68C },
["bus stop"]={ 0x1F68F },
["bust in silhouette"]={ 0x1F464 },
["busts in silhouette"]={ 0x1F465 },
+ ["butter"]={ 0x1F9C8 },
["butterfly"]={ 0x1F98B },
["cactus"]={ 0x1F335 },
["calendar"]={ 0x1F4C5 },
@@ -250,45 +203,40 @@ return {
["call me hand: medium skin tone"]={ 0x1F919, 0x1F3FD },
["call me hand: medium-dark skin tone"]={ 0x1F919, 0x1F3FE },
["call me hand: medium-light skin tone"]={ 0x1F919, 0x1F3FC },
- ["cambodia"]={ 0x1F1F0, 0x1F1ED },
["camel"]={ 0x1F42A },
["camera"]={ 0x1F4F7 },
["camera with flash"]={ 0x1F4F8 },
- ["cameroon"]={ 0x1F1E8, 0x1F1F2 },
- ["camping"]={ 0x1F3D5 },
- ["canada"]={ 0x1F1E8, 0x1F1E6 },
- ["canary islands"]={ 0x1F1EE, 0x1F1E8 },
+ ["camping"]={ 0x1F3D5, 0xFE0F },
["cancer"]={ 0x264B },
- ["candle"]={ 0x1F56F },
+ ["candle"]={ 0x1F56F, 0xFE0F },
["candy"]={ 0x1F36C },
["canned food"]={ 0x1F96B },
["canoe"]={ 0x1F6F6 },
- ["cape verde"]={ 0x1F1E8, 0x1F1FB },
["capricorn"]={ 0x2651 },
- ["card file box"]={ 0x1F5C3 },
+ ["card file box"]={ 0x1F5C3, 0xFE0F },
["card index"]={ 0x1F4C7 },
- ["card index dividers"]={ 0x1F5C2 },
- ["caribbean netherlands"]={ 0x1F1E7, 0x1F1F6 },
+ ["card index dividers"]={ 0x1F5C2, 0xFE0F },
["carousel horse"]={ 0x1F3A0 },
["carp streamer"]={ 0x1F38F },
["carrot"]={ 0x1F955 },
["castle"]={ 0x1F3F0 },
["cat"]={ 0x1F408 },
["cat face"]={ 0x1F431 },
- ["cat face with tears of joy"]={ 0x1F639 },
- ["cat face with wry smile"]={ 0x1F63C },
- ["cayman islands"]={ 0x1F1F0, 0x1F1FE },
- ["central african republic"]={ 0x1F1E8, 0x1F1EB },
- ["ceuta & melilla"]={ 0x1F1EA, 0x1F1E6 },
- ["chad"]={ 0x1F1F9, 0x1F1E9 },
- ["chains"]={ 0x26D3 },
+ ["cat with tears of joy"]={ 0x1F639 },
+ ["cat with wry smile"]={ 0x1F63C },
+ ["chains"]={ 0x26D3, 0xFE0F },
+ ["chair"]={ 0x1FA91 },
["chart decreasing"]={ 0x1F4C9 },
["chart increasing"]={ 0x1F4C8 },
["chart increasing with yen"]={ 0x1F4B9 },
+ ["check box with check"]={ 0x2611, 0xFE0F },
+ ["check mark"]={ 0x2714, 0xFE0F },
+ ["check mark button"]={ 0x2705 },
["cheese wedge"]={ 0x1F9C0 },
["chequered flag"]={ 0x1F3C1 },
["cherries"]={ 0x1F352 },
["cherry blossom"]={ 0x1F338 },
+ ["chess pawn"]={ 0x265F, 0xFE0F },
["chestnut"]={ 0x1F330 },
["chicken"]={ 0x1F414 },
["child"]={ 0x1F9D2 },
@@ -298,22 +246,19 @@ return {
["child: medium-dark skin tone"]={ 0x1F9D2, 0x1F3FE },
["child: medium-light skin tone"]={ 0x1F9D2, 0x1F3FC },
["children crossing"]={ 0x1F6B8 },
- ["chile"]={ 0x1F1E8, 0x1F1F1 },
- ["china"]={ 0x1F1E8, 0x1F1F3 },
- ["chipmunk"]={ 0x1F43F },
+ ["chipmunk"]={ 0x1F43F, 0xFE0F },
["chocolate bar"]={ 0x1F36B },
["chopsticks"]={ 0x1F962 },
- ["christmas island"]={ 0x1F1E8, 0x1F1FD },
["christmas tree"]={ 0x1F384 },
["church"]={ 0x26EA },
["cigarette"]={ 0x1F6AC },
["cinema"]={ 0x1F3A6 },
- ["circled m"]={ 0x24C2 },
+ ["circled m"]={ 0x24C2, 0xFE0F },
["circus tent"]={ 0x1F3AA },
- ["cityscape"]={ 0x1F3D9 },
+ ["cityscape"]={ 0x1F3D9, 0xFE0F },
["cityscape at dusk"]={ 0x1F306 },
["cl button"]={ 0x1F191 },
- ["clamp"]={ 0x1F5DC },
+ ["clamp"]={ 0x1F5DC, 0xFE0F },
["clapper board"]={ 0x1F3AC },
["clapping hands"]={ 0x1F44F },
["clapping hands: dark skin tone"]={ 0x1F44F, 0x1F3FF },
@@ -321,40 +266,36 @@ return {
["clapping hands: medium skin tone"]={ 0x1F44F, 0x1F3FD },
["clapping hands: medium-dark skin tone"]={ 0x1F44F, 0x1F3FE },
["clapping hands: medium-light skin tone"]={ 0x1F44F, 0x1F3FC },
- ["classical building"]={ 0x1F3DB },
+ ["classical building"]={ 0x1F3DB, 0xFE0F },
["clinking beer mugs"]={ 0x1F37B },
["clinking glasses"]={ 0x1F942 },
["clipboard"]={ 0x1F4CB },
- ["clipperton island"]={ 0x1F1E8, 0x1F1F5 },
["clockwise vertical arrows"]={ 0x1F503 },
["closed book"]={ 0x1F4D5 },
["closed mailbox with lowered flag"]={ 0x1F4EA },
["closed mailbox with raised flag"]={ 0x1F4EB },
["closed umbrella"]={ 0x1F302 },
- ["cloud"]={ 0x2601 },
- ["cloud with lightning"]={ 0x1F329 },
- ["cloud with lightning and rain"]={ 0x26C8 },
- ["cloud with rain"]={ 0x1F327 },
- ["cloud with snow"]={ 0x1F328 },
+ ["cloud"]={ 0x2601, 0xFE0F },
+ ["cloud with lightning"]={ 0x1F329, 0xFE0F },
+ ["cloud with lightning and rain"]={ 0x26C8, 0xFE0F },
+ ["cloud with rain"]={ 0x1F327, 0xFE0F },
+ ["cloud with snow"]={ 0x1F328, 0xFE0F },
["clown face"]={ 0x1F921 },
- ["club suit"]={ 0x2663 },
+ ["club suit"]={ 0x2663, 0xFE0F },
["clutch bag"]={ 0x1F45D },
["coat"]={ 0x1F9E5 },
["cocktail glass"]={ 0x1F378 },
["coconut"]={ 0x1F965 },
- ["cocos (keeling) islands"]={ 0x1F1E8, 0x1F1E8 },
- ["coffin"]={ 0x26B0 },
+ ["coffin"]={ 0x26B0, 0xFE0F },
+ ["cold face"]={ 0x1F976 },
["collision"]={ 0x1F4A5 },
- ["colombia"]={ 0x1F1E8, 0x1F1F4 },
- ["comet"]={ 0x2604 },
- ["comoros"]={ 0x1F1F0, 0x1F1F2 },
+ ["comet"]={ 0x2604, 0xFE0F },
+ ["compass"]={ 0x1F9ED },
["computer disk"]={ 0x1F4BD },
- ["computer mouse"]={ 0x1F5B1 },
+ ["computer mouse"]={ 0x1F5B1, 0xFE0F },
["confetti ball"]={ 0x1F38A },
["confounded face"]={ 0x1F616 },
["confused face"]={ 0x1F615 },
- ["congo - brazzaville"]={ 0x1F1E8, 0x1F1EC },
- ["congo - kinshasa"]={ 0x1F1E8, 0x1F1E9 },
["construction"]={ 0x1F6A7 },
["construction worker"]={ 0x1F477 },
["construction worker: dark skin tone"]={ 0x1F477, 0x1F3FF },
@@ -362,30 +303,28 @@ return {
["construction worker: medium skin tone"]={ 0x1F477, 0x1F3FD },
["construction worker: medium-dark skin tone"]={ 0x1F477, 0x1F3FE },
["construction worker: medium-light skin tone"]={ 0x1F477, 0x1F3FC },
- ["control knobs"]={ 0x1F39B },
+ ["control knobs"]={ 0x1F39B, 0xFE0F },
["convenience store"]={ 0x1F3EA },
- ["cook islands"]={ 0x1F1E8, 0x1F1F0 },
["cooked rice"]={ 0x1F35A },
["cookie"]={ 0x1F36A },
["cooking"]={ 0x1F373 },
["cool button"]={ 0x1F192 },
- ["copyright"]={ 0xA9 },
- ["costa rica"]={ 0x1F1E8, 0x1F1F7 },
- ["couch and lamp"]={ 0x1F6CB },
+ ["copyright"]={ 0xA9, 0xFE0F },
+ ["couch and lamp"]={ 0x1F6CB, 0xFE0F },
+ ["counterclockwise arrows button"]={ 0x1F504 },
["couple with heart"]={ 0x1F491 },
- ["couple with heart: man, man"]={ 0x1F468, 0x200D, 0x2764, 0x200D, 0x1F468 },
- ["couple with heart: woman, man"]={ 0x1F469, 0x200D, 0x2764, 0x200D, 0x1F468 },
- ["couple with heart: woman, woman"]={ 0x1F469, 0x200D, 0x2764, 0x200D, 0x1F469 },
+ ["couple with heart: man, man"]={ 0x1F468, 0x200D, 0x2764, 0xFE0F, 0x200D, 0x1F468 },
+ ["couple with heart: woman, man"]={ 0x1F469, 0x200D, 0x2764, 0xFE0F, 0x200D, 0x1F468 },
+ ["couple with heart: woman, woman"]={ 0x1F469, 0x200D, 0x2764, 0xFE0F, 0x200D, 0x1F469 },
["cow"]={ 0x1F404 },
["cow face"]={ 0x1F42E },
["cowboy hat face"]={ 0x1F920 },
["crab"]={ 0x1F980 },
- ["crayon"]={ 0x1F58D },
- ["crazy face"]={ 0x1F92A },
+ ["crayon"]={ 0x1F58D, 0xFE0F },
["credit card"]={ 0x1F4B3 },
["crescent moon"]={ 0x1F319 },
- ["cricket"]={ 0x1F3CF },
- ["croatia"]={ 0x1F1ED, 0x1F1F7 },
+ ["cricket"]={ 0x1F997 },
+ ["cricket game"]={ 0x1F3CF },
["crocodile"]={ 0x1F40A },
["croissant"]={ 0x1F950 },
["cross mark"]={ 0x274C },
@@ -397,15 +336,14 @@ return {
["crossed fingers: medium-dark skin tone"]={ 0x1F91E, 0x1F3FE },
["crossed fingers: medium-light skin tone"]={ 0x1F91E, 0x1F3FC },
["crossed flags"]={ 0x1F38C },
- ["crossed swords"]={ 0x2694 },
+ ["crossed swords"]={ 0x2694, 0xFE0F },
["crown"]={ 0x1F451 },
- ["crying cat face"]={ 0x1F63F },
+ ["crying cat"]={ 0x1F63F },
["crying face"]={ 0x1F622 },
["crystal ball"]={ 0x1F52E },
- ["cuba"]={ 0x1F1E8, 0x1F1FA },
["cucumber"]={ 0x1F952 },
["cup with straw"]={ 0x1F964 },
- ["curaçao"]={ 0x1F1E8, 0x1F1FC },
+ ["cupcake"]={ 0x1F9C1 },
["curling stone"]={ 0x1F94C },
["curly loop"]={ 0x27B0 },
["currency exchange"]={ 0x1F4B1 },
@@ -414,57 +352,72 @@ return {
["customs"]={ 0x1F6C3 },
["cut of meat"]={ 0x1F969 },
["cyclone"]={ 0x1F300 },
- ["cyprus"]={ 0x1F1E8, 0x1F1FE },
- ["czechia"]={ 0x1F1E8, 0x1F1FF },
- ["côte d’ivoire"]={ 0x1F1E8, 0x1F1EE },
- ["dagger"]={ 0x1F5E1 },
+ ["dagger"]={ 0x1F5E1, 0xFE0F },
["dango"]={ 0x1F361 },
["dashing away"]={ 0x1F4A8 },
+ ["deaf man"]={ 0x1F9CF, 0x200D, 0x2642, 0xFE0F },
+ ["deaf man: dark skin tone"]={ 0x1F9CF, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["deaf man: light skin tone"]={ 0x1F9CF, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["deaf man: medium skin tone"]={ 0x1F9CF, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["deaf man: medium-dark skin tone"]={ 0x1F9CF, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["deaf man: medium-light skin tone"]={ 0x1F9CF, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["deaf person"]={ 0x1F9CF },
+ ["deaf person: dark skin tone"]={ 0x1F9CF, 0x1F3FF },
+ ["deaf person: light skin tone"]={ 0x1F9CF, 0x1F3FB },
+ ["deaf person: medium skin tone"]={ 0x1F9CF, 0x1F3FD },
+ ["deaf person: medium-dark skin tone"]={ 0x1F9CF, 0x1F3FE },
+ ["deaf person: medium-light skin tone"]={ 0x1F9CF, 0x1F3FC },
+ ["deaf woman"]={ 0x1F9CF, 0x200D, 0x2640, 0xFE0F },
+ ["deaf woman: dark skin tone"]={ 0x1F9CF, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["deaf woman: light skin tone"]={ 0x1F9CF, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["deaf woman: medium skin tone"]={ 0x1F9CF, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["deaf woman: medium-dark skin tone"]={ 0x1F9CF, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["deaf woman: medium-light skin tone"]={ 0x1F9CF, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
["deciduous tree"]={ 0x1F333 },
["deer"]={ 0x1F98C },
["delivery truck"]={ 0x1F69A },
- ["denmark"]={ 0x1F1E9, 0x1F1F0 },
["department store"]={ 0x1F3EC },
- ["derelict house"]={ 0x1F3DA },
- ["desert"]={ 0x1F3DC },
- ["desert island"]={ 0x1F3DD },
- ["desktop computer"]={ 0x1F5A5 },
- ["detective"]={ 0x1F575 },
+ ["derelict house"]={ 0x1F3DA, 0xFE0F },
+ ["desert"]={ 0x1F3DC, 0xFE0F },
+ ["desert island"]={ 0x1F3DD, 0xFE0F },
+ ["desktop computer"]={ 0x1F5A5, 0xFE0F },
+ ["detective"]={ 0x1F575, 0xFE0F },
["detective: dark skin tone"]={ 0x1F575, 0x1F3FF },
["detective: light skin tone"]={ 0x1F575, 0x1F3FB },
["detective: medium skin tone"]={ 0x1F575, 0x1F3FD },
["detective: medium-dark skin tone"]={ 0x1F575, 0x1F3FE },
["detective: medium-light skin tone"]={ 0x1F575, 0x1F3FC },
- ["diamond suit"]={ 0x2666 },
+ ["diamond suit"]={ 0x2666, 0xFE0F },
["diamond with a dot"]={ 0x1F4A0 },
- ["diego garcia"]={ 0x1F1E9, 0x1F1EC },
["dim button"]={ 0x1F505 },
["direct hit"]={ 0x1F3AF },
- ["disappointed but relieved face"]={ 0x1F625 },
["disappointed face"]={ 0x1F61E },
+ ["diving mask"]={ 0x1F93F },
+ ["division sign"]={ 0x2797 },
+ ["diya lamp"]={ 0x1FA94 },
["dizzy"]={ 0x1F4AB },
["dizzy face"]={ 0x1F635 },
- ["djibouti"]={ 0x1F1E9, 0x1F1EF },
+ ["dna"]={ 0x1F9EC },
["dog"]={ 0x1F415 },
["dog face"]={ 0x1F436 },
["dollar banknote"]={ 0x1F4B5 },
["dolphin"]={ 0x1F42C },
- ["dominica"]={ 0x1F1E9, 0x1F1F2 },
- ["dominican republic"]={ 0x1F1E9, 0x1F1F4 },
["door"]={ 0x1F6AA },
["dotted six-pointed star"]={ 0x1F52F },
["double curly loop"]={ 0x27BF },
- ["double exclamation mark"]={ 0x203C },
+ ["double exclamation mark"]={ 0x203C, 0xFE0F },
["doughnut"]={ 0x1F369 },
- ["dove"]={ 0x1F54A },
- ["down arrow"]={ 0x2B07 },
- ["down button"]={ 0x1F53D },
- ["down-left arrow"]={ 0x2199 },
- ["down-right arrow"]={ 0x2198 },
+ ["dove"]={ 0x1F54A, 0xFE0F },
+ ["down arrow"]={ 0x2B07, 0xFE0F },
+ ["down-left arrow"]={ 0x2199, 0xFE0F },
+ ["down-right arrow"]={ 0x2198, 0xFE0F },
+ ["downcast face with sweat"]={ 0x1F613 },
+ ["downwards button"]={ 0x1F53D },
["dragon"]={ 0x1F409 },
["dragon face"]={ 0x1F432 },
["dress"]={ 0x1F457 },
["drooling face"]={ 0x1F924 },
+ ["drop of blood"]={ 0x1FA78 },
["droplet"]={ 0x1F4A7 },
["drum"]={ 0x1F941 },
["duck"]={ 0x1F986 },
@@ -474,21 +427,24 @@ return {
["eagle"]={ 0x1F985 },
["ear"]={ 0x1F442 },
["ear of corn"]={ 0x1F33D },
+ ["ear with hearing aid"]={ 0x1F9BB },
+ ["ear with hearing aid: dark skin tone"]={ 0x1F9BB, 0x1F3FF },
+ ["ear with hearing aid: light skin tone"]={ 0x1F9BB, 0x1F3FB },
+ ["ear with hearing aid: medium skin tone"]={ 0x1F9BB, 0x1F3FD },
+ ["ear with hearing aid: medium-dark skin tone"]={ 0x1F9BB, 0x1F3FE },
+ ["ear with hearing aid: medium-light skin tone"]={ 0x1F9BB, 0x1F3FC },
["ear: dark skin tone"]={ 0x1F442, 0x1F3FF },
["ear: light skin tone"]={ 0x1F442, 0x1F3FB },
["ear: medium skin tone"]={ 0x1F442, 0x1F3FD },
["ear: medium-dark skin tone"]={ 0x1F442, 0x1F3FE },
["ear: medium-light skin tone"]={ 0x1F442, 0x1F3FC },
- ["ecuador"]={ 0x1F1EA, 0x1F1E8 },
["egg"]={ 0x1F95A },
["eggplant"]={ 0x1F346 },
- ["egypt"]={ 0x1F1EA, 0x1F1EC },
["eight o’clock"]={ 0x1F557 },
- ["eight-pointed star"]={ 0x2734 },
- ["eight-spoked asterisk"]={ 0x2733 },
+ ["eight-pointed star"]={ 0x2734, 0xFE0F },
+ ["eight-spoked asterisk"]={ 0x2733, 0xFE0F },
["eight-thirty"]={ 0x1F563 },
- ["eject button"]={ 0x23CF },
- ["el salvador"]={ 0x1F1F8, 0x1F1FB },
+ ["eject button"]={ 0x23CF, 0xFE0F },
["electric plug"]={ 0x1F50C },
["elephant"]={ 0x1F418 },
["eleven o’clock"]={ 0x1F55A },
@@ -500,44 +456,34 @@ return {
["elf: medium-dark skin tone"]={ 0x1F9DD, 0x1F3FE },
["elf: medium-light skin tone"]={ 0x1F9DD, 0x1F3FC },
["end arrow"]={ 0x1F51A },
- ["england"]={ 0x1F3F4, 0xE0067, 0xE0062, 0xE0065, 0xE006E, 0xE0067, 0xE007F },
- ["envelope"]={ 0x2709 },
+ ["envelope"]={ 0x2709, 0xFE0F },
["envelope with arrow"]={ 0x1F4E9 },
- ["equatorial guinea"]={ 0x1F1EC, 0x1F1F6 },
- ["eritrea"]={ 0x1F1EA, 0x1F1F7 },
- ["estonia"]={ 0x1F1EA, 0x1F1EA },
- ["ethiopia"]={ 0x1F1EA, 0x1F1F9 },
["euro banknote"]={ 0x1F4B6 },
- ["european union"]={ 0x1F1EA, 0x1F1FA },
["evergreen tree"]={ 0x1F332 },
["ewe"]={ 0x1F411 },
["exclamation mark"]={ 0x2757 },
- ["exclamation question mark"]={ 0x2049 },
+ ["exclamation question mark"]={ 0x2049, 0xFE0F },
["exploding head"]={ 0x1F92F },
["expressionless face"]={ 0x1F611 },
- ["eye"]={ 0x1F441 },
- ["eye in speech bubble"]={ 0x1F441, 0x200D, 0x1F5E8 },
+ ["eye"]={ 0x1F441, 0xFE0F },
+ ["eye in speech bubble"]={ 0x1F441, 0xFE0F, 0x200D, 0x1F5E8, 0xFE0F },
["eyes"]={ 0x1F440 },
["face blowing a kiss"]={ 0x1F618 },
- ["face savouring delicious food"]={ 0x1F60B },
+ ["face savoring food"]={ 0x1F60B },
["face screaming in fear"]={ 0x1F631 },
["face vomiting"]={ 0x1F92E },
- ["face with cold sweat"]={ 0x1F613 },
["face with hand over mouth"]={ 0x1F92D },
["face with head-bandage"]={ 0x1F915 },
["face with medical mask"]={ 0x1F637 },
["face with monocle"]={ 0x1F9D0 },
["face with open mouth"]={ 0x1F62E },
- ["face with open mouth & cold sweat"]={ 0x1F630 },
["face with raised eyebrow"]={ 0x1F928 },
["face with rolling eyes"]={ 0x1F644 },
["face with steam from nose"]={ 0x1F624 },
- ["face with stuck-out tongue"]={ 0x1F61B },
- ["face with stuck-out tongue & closed eyes"]={ 0x1F61D },
- ["face with stuck-out tongue & winking eye"]={ 0x1F61C },
- ["face with symbols over mouth"]={ 0x1F92C },
+ ["face with symbols on mouth"]={ 0x1F92C },
["face with tears of joy"]={ 0x1F602 },
["face with thermometer"]={ 0x1F912 },
+ ["face with tongue"]={ 0x1F61B },
["face without mouth"]={ 0x1F636 },
["factory"]={ 0x1F3ED },
["fairy"]={ 0x1F9DA },
@@ -546,7 +492,7 @@ return {
["fairy: medium skin tone"]={ 0x1F9DA, 0x1F3FD },
["fairy: medium-dark skin tone"]={ 0x1F9DA, 0x1F3FE },
["fairy: medium-light skin tone"]={ 0x1F9DA, 0x1F3FC },
- ["falkland islands"]={ 0x1F1EB, 0x1F1F0 },
+ ["falafel"]={ 0x1F9C6 },
["fallen leaf"]={ 0x1F342 },
["family"]={ 0x1F46A },
["family: man, boy"]={ 0x1F468, 0x200D, 0x1F466 },
@@ -574,36 +520,298 @@ return {
["family: woman, woman, girl"]={ 0x1F469, 0x200D, 0x1F469, 0x200D, 0x1F467 },
["family: woman, woman, girl, boy"]={ 0x1F469, 0x200D, 0x1F469, 0x200D, 0x1F467, 0x200D, 0x1F466 },
["family: woman, woman, girl, girl"]={ 0x1F469, 0x200D, 0x1F469, 0x200D, 0x1F467, 0x200D, 0x1F467 },
- ["faroe islands"]={ 0x1F1EB, 0x1F1F4 },
["fast down button"]={ 0x23EC },
["fast reverse button"]={ 0x23EA },
["fast up button"]={ 0x23EB },
["fast-forward button"]={ 0x23E9 },
["fax machine"]={ 0x1F4E0 },
["fearful face"]={ 0x1F628 },
- ["female sign"]={ 0x2640 },
+ ["female sign"]={ 0x2640, 0xFE0F },
["ferris wheel"]={ 0x1F3A1 },
- ["ferry"]={ 0x26F4 },
+ ["ferry"]={ 0x26F4, 0xFE0F },
["field hockey"]={ 0x1F3D1 },
- ["fiji"]={ 0x1F1EB, 0x1F1EF },
- ["file cabinet"]={ 0x1F5C4 },
+ ["file cabinet"]={ 0x1F5C4, 0xFE0F },
["file folder"]={ 0x1F4C1 },
- ["film frames"]={ 0x1F39E },
- ["film projector"]={ 0x1F4FD },
- ["finland"]={ 0x1F1EB, 0x1F1EE },
+ ["film frames"]={ 0x1F39E, 0xFE0F },
+ ["film projector"]={ 0x1F4FD, 0xFE0F },
["fire"]={ 0x1F525 },
["fire engine"]={ 0x1F692 },
+ ["fire extinguisher"]={ 0x1F9EF },
+ ["firecracker"]={ 0x1F9E8 },
["fireworks"]={ 0x1F386 },
["first quarter moon"]={ 0x1F313 },
- ["first quarter moon with face"]={ 0x1F31B },
+ ["first quarter moon face"]={ 0x1F31B },
["fish"]={ 0x1F41F },
["fish cake with swirl"]={ 0x1F365 },
["fishing pole"]={ 0x1F3A3 },
["five o’clock"]={ 0x1F554 },
["five-thirty"]={ 0x1F560 },
["flag in hole"]={ 0x26F3 },
+ ["flag: afghanistan"]={ 0x1F1E6, 0x1F1EB },
+ ["flag: albania"]={ 0x1F1E6, 0x1F1F1 },
+ ["flag: algeria"]={ 0x1F1E9, 0x1F1FF },
+ ["flag: american samoa"]={ 0x1F1E6, 0x1F1F8 },
+ ["flag: andorra"]={ 0x1F1E6, 0x1F1E9 },
+ ["flag: angola"]={ 0x1F1E6, 0x1F1F4 },
+ ["flag: anguilla"]={ 0x1F1E6, 0x1F1EE },
+ ["flag: antarctica"]={ 0x1F1E6, 0x1F1F6 },
+ ["flag: antigua & barbuda"]={ 0x1F1E6, 0x1F1EC },
+ ["flag: argentina"]={ 0x1F1E6, 0x1F1F7 },
+ ["flag: armenia"]={ 0x1F1E6, 0x1F1F2 },
+ ["flag: aruba"]={ 0x1F1E6, 0x1F1FC },
+ ["flag: ascension island"]={ 0x1F1E6, 0x1F1E8 },
+ ["flag: australia"]={ 0x1F1E6, 0x1F1FA },
+ ["flag: austria"]={ 0x1F1E6, 0x1F1F9 },
+ ["flag: azerbaijan"]={ 0x1F1E6, 0x1F1FF },
+ ["flag: bahamas"]={ 0x1F1E7, 0x1F1F8 },
+ ["flag: bahrain"]={ 0x1F1E7, 0x1F1ED },
+ ["flag: bangladesh"]={ 0x1F1E7, 0x1F1E9 },
+ ["flag: barbados"]={ 0x1F1E7, 0x1F1E7 },
+ ["flag: belarus"]={ 0x1F1E7, 0x1F1FE },
+ ["flag: belgium"]={ 0x1F1E7, 0x1F1EA },
+ ["flag: belize"]={ 0x1F1E7, 0x1F1FF },
+ ["flag: benin"]={ 0x1F1E7, 0x1F1EF },
+ ["flag: bermuda"]={ 0x1F1E7, 0x1F1F2 },
+ ["flag: bhutan"]={ 0x1F1E7, 0x1F1F9 },
+ ["flag: bolivia"]={ 0x1F1E7, 0x1F1F4 },
+ ["flag: bosnia & herzegovina"]={ 0x1F1E7, 0x1F1E6 },
+ ["flag: botswana"]={ 0x1F1E7, 0x1F1FC },
+ ["flag: bouvet island"]={ 0x1F1E7, 0x1F1FB },
+ ["flag: brazil"]={ 0x1F1E7, 0x1F1F7 },
+ ["flag: british indian ocean territory"]={ 0x1F1EE, 0x1F1F4 },
+ ["flag: british virgin islands"]={ 0x1F1FB, 0x1F1EC },
+ ["flag: brunei"]={ 0x1F1E7, 0x1F1F3 },
+ ["flag: bulgaria"]={ 0x1F1E7, 0x1F1EC },
+ ["flag: burkina faso"]={ 0x1F1E7, 0x1F1EB },
+ ["flag: burundi"]={ 0x1F1E7, 0x1F1EE },
+ ["flag: cambodia"]={ 0x1F1F0, 0x1F1ED },
+ ["flag: cameroon"]={ 0x1F1E8, 0x1F1F2 },
+ ["flag: canada"]={ 0x1F1E8, 0x1F1E6 },
+ ["flag: canary islands"]={ 0x1F1EE, 0x1F1E8 },
+ ["flag: cape verde"]={ 0x1F1E8, 0x1F1FB },
+ ["flag: caribbean netherlands"]={ 0x1F1E7, 0x1F1F6 },
+ ["flag: cayman islands"]={ 0x1F1F0, 0x1F1FE },
+ ["flag: central african republic"]={ 0x1F1E8, 0x1F1EB },
+ ["flag: ceuta & melilla"]={ 0x1F1EA, 0x1F1E6 },
+ ["flag: chad"]={ 0x1F1F9, 0x1F1E9 },
+ ["flag: chile"]={ 0x1F1E8, 0x1F1F1 },
+ ["flag: china"]={ 0x1F1E8, 0x1F1F3 },
+ ["flag: christmas island"]={ 0x1F1E8, 0x1F1FD },
+ ["flag: clipperton island"]={ 0x1F1E8, 0x1F1F5 },
+ ["flag: cocos (keeling) islands"]={ 0x1F1E8, 0x1F1E8 },
+ ["flag: colombia"]={ 0x1F1E8, 0x1F1F4 },
+ ["flag: comoros"]={ 0x1F1F0, 0x1F1F2 },
+ ["flag: congo - brazzaville"]={ 0x1F1E8, 0x1F1EC },
+ ["flag: congo - kinshasa"]={ 0x1F1E8, 0x1F1E9 },
+ ["flag: cook islands"]={ 0x1F1E8, 0x1F1F0 },
+ ["flag: costa rica"]={ 0x1F1E8, 0x1F1F7 },
+ ["flag: croatia"]={ 0x1F1ED, 0x1F1F7 },
+ ["flag: cuba"]={ 0x1F1E8, 0x1F1FA },
+ ["flag: curaçao"]={ 0x1F1E8, 0x1F1FC },
+ ["flag: cyprus"]={ 0x1F1E8, 0x1F1FE },
+ ["flag: czechia"]={ 0x1F1E8, 0x1F1FF },
+ ["flag: côte d’ivoire"]={ 0x1F1E8, 0x1F1EE },
+ ["flag: denmark"]={ 0x1F1E9, 0x1F1F0 },
+ ["flag: diego garcia"]={ 0x1F1E9, 0x1F1EC },
+ ["flag: djibouti"]={ 0x1F1E9, 0x1F1EF },
+ ["flag: dominica"]={ 0x1F1E9, 0x1F1F2 },
+ ["flag: dominican republic"]={ 0x1F1E9, 0x1F1F4 },
+ ["flag: ecuador"]={ 0x1F1EA, 0x1F1E8 },
+ ["flag: egypt"]={ 0x1F1EA, 0x1F1EC },
+ ["flag: el salvador"]={ 0x1F1F8, 0x1F1FB },
+ ["flag: england"]={ 0x1F3F4, 0xE0067, 0xE0062, 0xE0065, 0xE006E, 0xE0067, 0xE007F },
+ ["flag: equatorial guinea"]={ 0x1F1EC, 0x1F1F6 },
+ ["flag: eritrea"]={ 0x1F1EA, 0x1F1F7 },
+ ["flag: estonia"]={ 0x1F1EA, 0x1F1EA },
+ ["flag: eswatini"]={ 0x1F1F8, 0x1F1FF },
+ ["flag: ethiopia"]={ 0x1F1EA, 0x1F1F9 },
+ ["flag: european union"]={ 0x1F1EA, 0x1F1FA },
+ ["flag: falkland islands"]={ 0x1F1EB, 0x1F1F0 },
+ ["flag: faroe islands"]={ 0x1F1EB, 0x1F1F4 },
+ ["flag: fiji"]={ 0x1F1EB, 0x1F1EF },
+ ["flag: finland"]={ 0x1F1EB, 0x1F1EE },
+ ["flag: france"]={ 0x1F1EB, 0x1F1F7 },
+ ["flag: french guiana"]={ 0x1F1EC, 0x1F1EB },
+ ["flag: french polynesia"]={ 0x1F1F5, 0x1F1EB },
+ ["flag: french southern territories"]={ 0x1F1F9, 0x1F1EB },
+ ["flag: gabon"]={ 0x1F1EC, 0x1F1E6 },
+ ["flag: gambia"]={ 0x1F1EC, 0x1F1F2 },
+ ["flag: georgia"]={ 0x1F1EC, 0x1F1EA },
+ ["flag: germany"]={ 0x1F1E9, 0x1F1EA },
+ ["flag: ghana"]={ 0x1F1EC, 0x1F1ED },
+ ["flag: gibraltar"]={ 0x1F1EC, 0x1F1EE },
+ ["flag: greece"]={ 0x1F1EC, 0x1F1F7 },
+ ["flag: greenland"]={ 0x1F1EC, 0x1F1F1 },
+ ["flag: grenada"]={ 0x1F1EC, 0x1F1E9 },
+ ["flag: guadeloupe"]={ 0x1F1EC, 0x1F1F5 },
+ ["flag: guam"]={ 0x1F1EC, 0x1F1FA },
+ ["flag: guatemala"]={ 0x1F1EC, 0x1F1F9 },
+ ["flag: guernsey"]={ 0x1F1EC, 0x1F1EC },
+ ["flag: guinea"]={ 0x1F1EC, 0x1F1F3 },
+ ["flag: guinea-bissau"]={ 0x1F1EC, 0x1F1FC },
+ ["flag: guyana"]={ 0x1F1EC, 0x1F1FE },
+ ["flag: haiti"]={ 0x1F1ED, 0x1F1F9 },
+ ["flag: heard & mcdonald islands"]={ 0x1F1ED, 0x1F1F2 },
+ ["flag: honduras"]={ 0x1F1ED, 0x1F1F3 },
+ ["flag: hong kong sar china"]={ 0x1F1ED, 0x1F1F0 },
+ ["flag: hungary"]={ 0x1F1ED, 0x1F1FA },
+ ["flag: iceland"]={ 0x1F1EE, 0x1F1F8 },
+ ["flag: india"]={ 0x1F1EE, 0x1F1F3 },
+ ["flag: indonesia"]={ 0x1F1EE, 0x1F1E9 },
+ ["flag: iran"]={ 0x1F1EE, 0x1F1F7 },
+ ["flag: iraq"]={ 0x1F1EE, 0x1F1F6 },
+ ["flag: ireland"]={ 0x1F1EE, 0x1F1EA },
+ ["flag: isle of man"]={ 0x1F1EE, 0x1F1F2 },
+ ["flag: israel"]={ 0x1F1EE, 0x1F1F1 },
+ ["flag: italy"]={ 0x1F1EE, 0x1F1F9 },
+ ["flag: jamaica"]={ 0x1F1EF, 0x1F1F2 },
+ ["flag: japan"]={ 0x1F1EF, 0x1F1F5 },
+ ["flag: jersey"]={ 0x1F1EF, 0x1F1EA },
+ ["flag: jordan"]={ 0x1F1EF, 0x1F1F4 },
+ ["flag: kazakhstan"]={ 0x1F1F0, 0x1F1FF },
+ ["flag: kenya"]={ 0x1F1F0, 0x1F1EA },
+ ["flag: kiribati"]={ 0x1F1F0, 0x1F1EE },
+ ["flag: kosovo"]={ 0x1F1FD, 0x1F1F0 },
+ ["flag: kuwait"]={ 0x1F1F0, 0x1F1FC },
+ ["flag: kyrgyzstan"]={ 0x1F1F0, 0x1F1EC },
+ ["flag: laos"]={ 0x1F1F1, 0x1F1E6 },
+ ["flag: latvia"]={ 0x1F1F1, 0x1F1FB },
+ ["flag: lebanon"]={ 0x1F1F1, 0x1F1E7 },
+ ["flag: lesotho"]={ 0x1F1F1, 0x1F1F8 },
+ ["flag: liberia"]={ 0x1F1F1, 0x1F1F7 },
+ ["flag: libya"]={ 0x1F1F1, 0x1F1FE },
+ ["flag: liechtenstein"]={ 0x1F1F1, 0x1F1EE },
+ ["flag: lithuania"]={ 0x1F1F1, 0x1F1F9 },
+ ["flag: luxembourg"]={ 0x1F1F1, 0x1F1FA },
+ ["flag: macao sar china"]={ 0x1F1F2, 0x1F1F4 },
+ ["flag: macedonia"]={ 0x1F1F2, 0x1F1F0 },
+ ["flag: madagascar"]={ 0x1F1F2, 0x1F1EC },
+ ["flag: malawi"]={ 0x1F1F2, 0x1F1FC },
+ ["flag: malaysia"]={ 0x1F1F2, 0x1F1FE },
+ ["flag: maldives"]={ 0x1F1F2, 0x1F1FB },
+ ["flag: mali"]={ 0x1F1F2, 0x1F1F1 },
+ ["flag: malta"]={ 0x1F1F2, 0x1F1F9 },
+ ["flag: marshall islands"]={ 0x1F1F2, 0x1F1ED },
+ ["flag: martinique"]={ 0x1F1F2, 0x1F1F6 },
+ ["flag: mauritania"]={ 0x1F1F2, 0x1F1F7 },
+ ["flag: mauritius"]={ 0x1F1F2, 0x1F1FA },
+ ["flag: mayotte"]={ 0x1F1FE, 0x1F1F9 },
+ ["flag: mexico"]={ 0x1F1F2, 0x1F1FD },
+ ["flag: micronesia"]={ 0x1F1EB, 0x1F1F2 },
+ ["flag: moldova"]={ 0x1F1F2, 0x1F1E9 },
+ ["flag: monaco"]={ 0x1F1F2, 0x1F1E8 },
+ ["flag: mongolia"]={ 0x1F1F2, 0x1F1F3 },
+ ["flag: montenegro"]={ 0x1F1F2, 0x1F1EA },
+ ["flag: montserrat"]={ 0x1F1F2, 0x1F1F8 },
+ ["flag: morocco"]={ 0x1F1F2, 0x1F1E6 },
+ ["flag: mozambique"]={ 0x1F1F2, 0x1F1FF },
+ ["flag: myanmar (burma)"]={ 0x1F1F2, 0x1F1F2 },
+ ["flag: namibia"]={ 0x1F1F3, 0x1F1E6 },
+ ["flag: nauru"]={ 0x1F1F3, 0x1F1F7 },
+ ["flag: nepal"]={ 0x1F1F3, 0x1F1F5 },
+ ["flag: netherlands"]={ 0x1F1F3, 0x1F1F1 },
+ ["flag: new caledonia"]={ 0x1F1F3, 0x1F1E8 },
+ ["flag: new zealand"]={ 0x1F1F3, 0x1F1FF },
+ ["flag: nicaragua"]={ 0x1F1F3, 0x1F1EE },
+ ["flag: niger"]={ 0x1F1F3, 0x1F1EA },
+ ["flag: nigeria"]={ 0x1F1F3, 0x1F1EC },
+ ["flag: niue"]={ 0x1F1F3, 0x1F1FA },
+ ["flag: norfolk island"]={ 0x1F1F3, 0x1F1EB },
+ ["flag: north korea"]={ 0x1F1F0, 0x1F1F5 },
+ ["flag: northern mariana islands"]={ 0x1F1F2, 0x1F1F5 },
+ ["flag: norway"]={ 0x1F1F3, 0x1F1F4 },
+ ["flag: oman"]={ 0x1F1F4, 0x1F1F2 },
+ ["flag: pakistan"]={ 0x1F1F5, 0x1F1F0 },
+ ["flag: palau"]={ 0x1F1F5, 0x1F1FC },
+ ["flag: palestinian territories"]={ 0x1F1F5, 0x1F1F8 },
+ ["flag: panama"]={ 0x1F1F5, 0x1F1E6 },
+ ["flag: papua new guinea"]={ 0x1F1F5, 0x1F1EC },
+ ["flag: paraguay"]={ 0x1F1F5, 0x1F1FE },
+ ["flag: peru"]={ 0x1F1F5, 0x1F1EA },
+ ["flag: philippines"]={ 0x1F1F5, 0x1F1ED },
+ ["flag: pitcairn islands"]={ 0x1F1F5, 0x1F1F3 },
+ ["flag: poland"]={ 0x1F1F5, 0x1F1F1 },
+ ["flag: portugal"]={ 0x1F1F5, 0x1F1F9 },
+ ["flag: puerto rico"]={ 0x1F1F5, 0x1F1F7 },
+ ["flag: qatar"]={ 0x1F1F6, 0x1F1E6 },
+ ["flag: romania"]={ 0x1F1F7, 0x1F1F4 },
+ ["flag: russia"]={ 0x1F1F7, 0x1F1FA },
+ ["flag: rwanda"]={ 0x1F1F7, 0x1F1FC },
+ ["flag: réunion"]={ 0x1F1F7, 0x1F1EA },
+ ["flag: samoa"]={ 0x1F1FC, 0x1F1F8 },
+ ["flag: san marino"]={ 0x1F1F8, 0x1F1F2 },
+ ["flag: saudi arabia"]={ 0x1F1F8, 0x1F1E6 },
+ ["flag: scotland"]={ 0x1F3F4, 0xE0067, 0xE0062, 0xE0073, 0xE0063, 0xE0074, 0xE007F },
+ ["flag: senegal"]={ 0x1F1F8, 0x1F1F3 },
+ ["flag: serbia"]={ 0x1F1F7, 0x1F1F8 },
+ ["flag: seychelles"]={ 0x1F1F8, 0x1F1E8 },
+ ["flag: sierra leone"]={ 0x1F1F8, 0x1F1F1 },
+ ["flag: singapore"]={ 0x1F1F8, 0x1F1EC },
+ ["flag: sint maarten"]={ 0x1F1F8, 0x1F1FD },
+ ["flag: slovakia"]={ 0x1F1F8, 0x1F1F0 },
+ ["flag: slovenia"]={ 0x1F1F8, 0x1F1EE },
+ ["flag: solomon islands"]={ 0x1F1F8, 0x1F1E7 },
+ ["flag: somalia"]={ 0x1F1F8, 0x1F1F4 },
+ ["flag: south africa"]={ 0x1F1FF, 0x1F1E6 },
+ ["flag: south georgia & south sandwich islands"]={ 0x1F1EC, 0x1F1F8 },
+ ["flag: south korea"]={ 0x1F1F0, 0x1F1F7 },
+ ["flag: south sudan"]={ 0x1F1F8, 0x1F1F8 },
+ ["flag: spain"]={ 0x1F1EA, 0x1F1F8 },
+ ["flag: sri lanka"]={ 0x1F1F1, 0x1F1F0 },
+ ["flag: st. barthélemy"]={ 0x1F1E7, 0x1F1F1 },
+ ["flag: st. helena"]={ 0x1F1F8, 0x1F1ED },
+ ["flag: st. kitts & nevis"]={ 0x1F1F0, 0x1F1F3 },
+ ["flag: st. lucia"]={ 0x1F1F1, 0x1F1E8 },
+ ["flag: st. martin"]={ 0x1F1F2, 0x1F1EB },
+ ["flag: st. pierre & miquelon"]={ 0x1F1F5, 0x1F1F2 },
+ ["flag: st. vincent & grenadines"]={ 0x1F1FB, 0x1F1E8 },
+ ["flag: sudan"]={ 0x1F1F8, 0x1F1E9 },
+ ["flag: suriname"]={ 0x1F1F8, 0x1F1F7 },
+ ["flag: svalbard & jan mayen"]={ 0x1F1F8, 0x1F1EF },
+ ["flag: sweden"]={ 0x1F1F8, 0x1F1EA },
+ ["flag: switzerland"]={ 0x1F1E8, 0x1F1ED },
+ ["flag: syria"]={ 0x1F1F8, 0x1F1FE },
+ ["flag: são tomé & príncipe"]={ 0x1F1F8, 0x1F1F9 },
+ ["flag: taiwan"]={ 0x1F1F9, 0x1F1FC },
+ ["flag: tajikistan"]={ 0x1F1F9, 0x1F1EF },
+ ["flag: tanzania"]={ 0x1F1F9, 0x1F1FF },
+ ["flag: thailand"]={ 0x1F1F9, 0x1F1ED },
+ ["flag: timor-leste"]={ 0x1F1F9, 0x1F1F1 },
+ ["flag: togo"]={ 0x1F1F9, 0x1F1EC },
+ ["flag: tokelau"]={ 0x1F1F9, 0x1F1F0 },
+ ["flag: tonga"]={ 0x1F1F9, 0x1F1F4 },
+ ["flag: trinidad & tobago"]={ 0x1F1F9, 0x1F1F9 },
+ ["flag: tristan da cunha"]={ 0x1F1F9, 0x1F1E6 },
+ ["flag: tunisia"]={ 0x1F1F9, 0x1F1F3 },
+ ["flag: turkey"]={ 0x1F1F9, 0x1F1F7 },
+ ["flag: turkmenistan"]={ 0x1F1F9, 0x1F1F2 },
+ ["flag: turks & caicos islands"]={ 0x1F1F9, 0x1F1E8 },
+ ["flag: tuvalu"]={ 0x1F1F9, 0x1F1FB },
+ ["flag: u.s. outlying islands"]={ 0x1F1FA, 0x1F1F2 },
+ ["flag: u.s. virgin islands"]={ 0x1F1FB, 0x1F1EE },
+ ["flag: uganda"]={ 0x1F1FA, 0x1F1EC },
+ ["flag: ukraine"]={ 0x1F1FA, 0x1F1E6 },
+ ["flag: united arab emirates"]={ 0x1F1E6, 0x1F1EA },
+ ["flag: united kingdom"]={ 0x1F1EC, 0x1F1E7 },
+ ["flag: united nations"]={ 0x1F1FA, 0x1F1F3 },
+ ["flag: united states"]={ 0x1F1FA, 0x1F1F8 },
+ ["flag: uruguay"]={ 0x1F1FA, 0x1F1FE },
+ ["flag: uzbekistan"]={ 0x1F1FA, 0x1F1FF },
+ ["flag: vanuatu"]={ 0x1F1FB, 0x1F1FA },
+ ["flag: vatican city"]={ 0x1F1FB, 0x1F1E6 },
+ ["flag: venezuela"]={ 0x1F1FB, 0x1F1EA },
+ ["flag: vietnam"]={ 0x1F1FB, 0x1F1F3 },
+ ["flag: wales"]={ 0x1F3F4, 0xE0067, 0xE0062, 0xE0077, 0xE006C, 0xE0073, 0xE007F },
+ ["flag: wallis & futuna"]={ 0x1F1FC, 0x1F1EB },
+ ["flag: western sahara"]={ 0x1F1EA, 0x1F1ED },
+ ["flag: yemen"]={ 0x1F1FE, 0x1F1EA },
+ ["flag: zambia"]={ 0x1F1FF, 0x1F1F2 },
+ ["flag: zimbabwe"]={ 0x1F1FF, 0x1F1FC },
+ ["flag: Åland islands"]={ 0x1F1E6, 0x1F1FD },
+ ["flamingo"]={ 0x1F9A9 },
["flashlight"]={ 0x1F526 },
- ["fleur-de-lis"]={ 0x269C },
+ ["flat shoe"]={ 0x1F97F },
+ ["fleur-de-lis"]={ 0x269C, 0xFE0F },
["flexed biceps"]={ 0x1F4AA },
["flexed biceps: dark skin tone"]={ 0x1F4AA, 0x1F3FF },
["flexed biceps: light skin tone"]={ 0x1F4AA, 0x1F3FB },
@@ -613,8 +821,9 @@ return {
["floppy disk"]={ 0x1F4BE },
["flower playing cards"]={ 0x1F3B4 },
["flushed face"]={ 0x1F633 },
+ ["flying disc"]={ 0x1F94F },
["flying saucer"]={ 0x1F6F8 },
- ["fog"]={ 0x1F32B },
+ ["fog"]={ 0x1F32B, 0xFE0F },
["foggy"]={ 0x1F301 },
["folded hands"]={ 0x1F64F },
["folded hands: dark skin tone"]={ 0x1F64F, 0x1F3FF },
@@ -622,44 +831,41 @@ return {
["folded hands: medium skin tone"]={ 0x1F64F, 0x1F3FD },
["folded hands: medium-dark skin tone"]={ 0x1F64F, 0x1F3FE },
["folded hands: medium-light skin tone"]={ 0x1F64F, 0x1F3FC },
+ ["foot"]={ 0x1F9B6 },
+ ["foot: dark skin tone"]={ 0x1F9B6, 0x1F3FF },
+ ["foot: light skin tone"]={ 0x1F9B6, 0x1F3FB },
+ ["foot: medium skin tone"]={ 0x1F9B6, 0x1F3FD },
+ ["foot: medium-dark skin tone"]={ 0x1F9B6, 0x1F3FE },
+ ["foot: medium-light skin tone"]={ 0x1F9B6, 0x1F3FC },
["footprints"]={ 0x1F463 },
["fork and knife"]={ 0x1F374 },
- ["fork and knife with plate"]={ 0x1F37D },
+ ["fork and knife with plate"]={ 0x1F37D, 0xFE0F },
["fortune cookie"]={ 0x1F960 },
["fountain"]={ 0x26F2 },
- ["fountain pen"]={ 0x1F58B },
+ ["fountain pen"]={ 0x1F58B, 0xFE0F },
["four leaf clover"]={ 0x1F340 },
["four o’clock"]={ 0x1F553 },
["four-thirty"]={ 0x1F55F },
- ["fox face"]={ 0x1F98A },
- ["framed picture"]={ 0x1F5BC },
- ["france"]={ 0x1F1EB, 0x1F1F7 },
+ ["fox"]={ 0x1F98A },
+ ["framed picture"]={ 0x1F5BC, 0xFE0F },
["free button"]={ 0x1F193 },
["french fries"]={ 0x1F35F },
- ["french guiana"]={ 0x1F1EC, 0x1F1EB },
- ["french polynesia"]={ 0x1F1F5, 0x1F1EB },
- ["french southern territories"]={ 0x1F1F9, 0x1F1EB },
["fried shrimp"]={ 0x1F364 },
- ["frog face"]={ 0x1F438 },
+ ["frog"]={ 0x1F438 },
["front-facing baby chick"]={ 0x1F425 },
- ["frowning face"]={ 0x2639 },
+ ["frowning face"]={ 0x2639, 0xFE0F },
["frowning face with open mouth"]={ 0x1F626 },
["fuel pump"]={ 0x26FD },
["full moon"]={ 0x1F315 },
- ["full moon with face"]={ 0x1F31D },
- ["funeral urn"]={ 0x26B1 },
- ["gabon"]={ 0x1F1EC, 0x1F1E6 },
- ["gambia"]={ 0x1F1EC, 0x1F1F2 },
+ ["full moon face"]={ 0x1F31D },
+ ["funeral urn"]={ 0x26B1, 0xFE0F },
["game die"]={ 0x1F3B2 },
- ["gear"]={ 0x2699 },
+ ["garlic"]={ 0x1F9C4 },
+ ["gear"]={ 0x2699, 0xFE0F },
["gem stone"]={ 0x1F48E },
["gemini"]={ 0x264A },
["genie"]={ 0x1F9DE },
- ["georgia"]={ 0x1F1EC, 0x1F1EA },
- ["germany"]={ 0x1F1E9, 0x1F1EA },
- ["ghana"]={ 0x1F1EC, 0x1F1ED },
["ghost"]={ 0x1F47B },
- ["gibraltar"]={ 0x1F1EC, 0x1F1EE },
["giraffe"]={ 0x1F992 },
["girl"]={ 0x1F467 },
["girl: dark skin tone"]={ 0x1F467, 0x1F3FF },
@@ -678,59 +884,55 @@ return {
["goal net"]={ 0x1F945 },
["goat"]={ 0x1F410 },
["goblin"]={ 0x1F47A },
+ ["goggles"]={ 0x1F97D },
["gorilla"]={ 0x1F98D },
["graduation cap"]={ 0x1F393 },
["grapes"]={ 0x1F347 },
- ["greece"]={ 0x1F1EC, 0x1F1F7 },
["green apple"]={ 0x1F34F },
["green book"]={ 0x1F4D7 },
+ ["green circle"]={ 0x1F7E2 },
["green heart"]={ 0x1F49A },
["green salad"]={ 0x1F957 },
- ["greenland"]={ 0x1F1EC, 0x1F1F1 },
- ["grenada"]={ 0x1F1EC, 0x1F1E9 },
+ ["green square"]={ 0x1F7E9 },
["grimacing face"]={ 0x1F62C },
- ["grinning cat face with smiling eyes"]={ 0x1F638 },
+ ["grinning cat"]={ 0x1F63A },
+ ["grinning cat with smiling eyes"]={ 0x1F638 },
["grinning face"]={ 0x1F600 },
- ["grinning face with smiling eyes"]={ 0x1F601 },
+ ["grinning face with big eyes"]={ 0x1F603 },
+ ["grinning face with smiling eyes"]={ 0x1F604 },
+ ["grinning face with sweat"]={ 0x1F605 },
+ ["grinning squinting face"]={ 0x1F606 },
["growing heart"]={ 0x1F497 },
- ["guadeloupe"]={ 0x1F1EC, 0x1F1F5 },
- ["guam"]={ 0x1F1EC, 0x1F1FA },
["guard"]={ 0x1F482 },
["guard: dark skin tone"]={ 0x1F482, 0x1F3FF },
["guard: light skin tone"]={ 0x1F482, 0x1F3FB },
["guard: medium skin tone"]={ 0x1F482, 0x1F3FD },
["guard: medium-dark skin tone"]={ 0x1F482, 0x1F3FE },
["guard: medium-light skin tone"]={ 0x1F482, 0x1F3FC },
- ["guatemala"]={ 0x1F1EC, 0x1F1F9 },
- ["guernsey"]={ 0x1F1EC, 0x1F1EC },
- ["guinea"]={ 0x1F1EC, 0x1F1F3 },
- ["guinea-bissau"]={ 0x1F1EC, 0x1F1FC },
+ ["guide dog"]={ 0x1F9AE },
["guitar"]={ 0x1F3B8 },
- ["guyana"]={ 0x1F1EC, 0x1F1FE },
- ["haiti"]={ 0x1F1ED, 0x1F1F9 },
["hamburger"]={ 0x1F354 },
["hammer"]={ 0x1F528 },
- ["hammer and pick"]={ 0x2692 },
- ["hammer and wrench"]={ 0x1F6E0 },
- ["hamster face"]={ 0x1F439 },
+ ["hammer and pick"]={ 0x2692, 0xFE0F },
+ ["hammer and wrench"]={ 0x1F6E0, 0xFE0F },
+ ["hamster"]={ 0x1F439 },
+ ["hand with fingers splayed"]={ 0x1F590, 0xFE0F },
+ ["hand with fingers splayed: dark skin tone"]={ 0x1F590, 0x1F3FF },
+ ["hand with fingers splayed: light skin tone"]={ 0x1F590, 0x1F3FB },
+ ["hand with fingers splayed: medium skin tone"]={ 0x1F590, 0x1F3FD },
+ ["hand with fingers splayed: medium-dark skin tone"]={ 0x1F590, 0x1F3FE },
+ ["hand with fingers splayed: medium-light skin tone"]={ 0x1F590, 0x1F3FC },
["handbag"]={ 0x1F45C },
["handshake"]={ 0x1F91D },
["hatching chick"]={ 0x1F423 },
["headphone"]={ 0x1F3A7 },
["hear-no-evil monkey"]={ 0x1F649 },
- ["heard & mcdonald islands"]={ 0x1F1ED, 0x1F1F2 },
["heart decoration"]={ 0x1F49F },
- ["heart suit"]={ 0x2665 },
+ ["heart exclamation"]={ 0x2763, 0xFE0F },
+ ["heart suit"]={ 0x2665, 0xFE0F },
["heart with arrow"]={ 0x1F498 },
["heart with ribbon"]={ 0x1F49D },
- ["heavy check mark"]={ 0x2714 },
- ["heavy division sign"]={ 0x2797 },
["heavy dollar sign"]={ 0x1F4B2 },
- ["heavy heart exclamation"]={ 0x2763 },
- ["heavy large circle"]={ 0x2B55 },
- ["heavy minus sign"]={ 0x2796 },
- ["heavy multiplication x"]={ 0x2716 },
- ["heavy plus sign"]={ 0x2795 },
["hedgehog"]={ 0x1F994 },
["helicopter"]={ 0x1F681 },
["herb"]={ 0x1F33F },
@@ -738,12 +940,13 @@ return {
["high voltage"]={ 0x26A1 },
["high-heeled shoe"]={ 0x1F460 },
["high-speed train"]={ 0x1F684 },
- ["high-speed train with bullet nose"]={ 0x1F685 },
- ["hole"]={ 0x1F573 },
- ["honduras"]={ 0x1F1ED, 0x1F1F3 },
+ ["hiking boot"]={ 0x1F97E },
+ ["hindu temple"]={ 0x1F6D5 },
+ ["hippopotamus"]={ 0x1F99B },
+ ["hole"]={ 0x1F573, 0xFE0F },
+ ["hollow red circle"]={ 0x2B55 },
["honey pot"]={ 0x1F36F },
["honeybee"]={ 0x1F41D },
- ["hong kong sar china"]={ 0x1F1ED, 0x1F1F0 },
["horizontal traffic light"]={ 0x1F6A5 },
["horse"]={ 0x1F40E },
["horse face"]={ 0x1F434 },
@@ -756,47 +959,39 @@ return {
["hospital"]={ 0x1F3E5 },
["hot beverage"]={ 0x2615 },
["hot dog"]={ 0x1F32D },
- ["hot pepper"]={ 0x1F336 },
- ["hot springs"]={ 0x2668 },
+ ["hot face"]={ 0x1F975 },
+ ["hot pepper"]={ 0x1F336, 0xFE0F },
+ ["hot springs"]={ 0x2668, 0xFE0F },
["hotel"]={ 0x1F3E8 },
- ["hourglass"]={ 0x231B },
- ["hourglass with flowing sand"]={ 0x23F3 },
+ ["hourglass done"]={ 0x231B },
+ ["hourglass not done"]={ 0x23F3 },
["house"]={ 0x1F3E0 },
["house with garden"]={ 0x1F3E1 },
+ ["houses"]={ 0x1F3D8, 0xFE0F },
["hugging face"]={ 0x1F917 },
["hundred points"]={ 0x1F4AF },
- ["hungary"]={ 0x1F1ED, 0x1F1FA },
["hushed face"]={ 0x1F62F },
["ice cream"]={ 0x1F368 },
+ ["ice cube"]={ 0x1F9CA },
["ice hockey"]={ 0x1F3D2 },
- ["ice skate"]={ 0x26F8 },
- ["iceland"]={ 0x1F1EE, 0x1F1F8 },
+ ["ice skate"]={ 0x26F8, 0xFE0F },
["id button"]={ 0x1F194 },
["inbox tray"]={ 0x1F4E5 },
["incoming envelope"]={ 0x1F4E8 },
- ["index pointing up"]={ 0x261D },
+ ["index pointing up"]={ 0x261D, 0xFE0F },
["index pointing up: dark skin tone"]={ 0x261D, 0x1F3FF },
["index pointing up: light skin tone"]={ 0x261D, 0x1F3FB },
["index pointing up: medium skin tone"]={ 0x261D, 0x1F3FD },
["index pointing up: medium-dark skin tone"]={ 0x261D, 0x1F3FE },
["index pointing up: medium-light skin tone"]={ 0x261D, 0x1F3FC },
- ["india"]={ 0x1F1EE, 0x1F1F3 },
- ["indonesia"]={ 0x1F1EE, 0x1F1E9 },
- ["information"]={ 0x2139 },
+ ["infinity"]={ 0x267E, 0xFE0F },
+ ["information"]={ 0x2139, 0xFE0F },
["input latin letters"]={ 0x1F524 },
["input latin lowercase"]={ 0x1F521 },
["input latin uppercase"]={ 0x1F520 },
["input numbers"]={ 0x1F522 },
["input symbols"]={ 0x1F523 },
- ["iran"]={ 0x1F1EE, 0x1F1F7 },
- ["iraq"]={ 0x1F1EE, 0x1F1F6 },
- ["ireland"]={ 0x1F1EE, 0x1F1EA },
- ["isle of man"]={ 0x1F1EE, 0x1F1F2 },
- ["israel"]={ 0x1F1EE, 0x1F1F1 },
- ["italy"]={ 0x1F1EE, 0x1F1F9 },
["jack-o-lantern"]={ 0x1F383 },
- ["jamaica"]={ 0x1F1EF, 0x1F1F2 },
- ["japan"]={ 0x1F1EF, 0x1F1F5 },
["japanese castle"]={ 0x1F3EF },
["japanese dolls"]={ 0x1F38E },
["japanese post office"]={ 0x1F3E3 },
@@ -804,110 +999,107 @@ return {
["japanese “acceptable” button"]={ 0x1F251 },
["japanese “application” button"]={ 0x1F238 },
["japanese “bargain” button"]={ 0x1F250 },
- ["japanese “congratulations” button"]={ 0x3297 },
+ ["japanese “congratulations” button"]={ 0x3297, 0xFE0F },
["japanese “discount” button"]={ 0x1F239 },
["japanese “free of charge” button"]={ 0x1F21A },
["japanese “here” button"]={ 0x1F201 },
- ["japanese “monthly amount” button"]={ 0x1F237 },
+ ["japanese “monthly amount” button"]={ 0x1F237, 0xFE0F },
["japanese “no vacancy” button"]={ 0x1F235 },
["japanese “not free of charge” button"]={ 0x1F236 },
["japanese “open for business” button"]={ 0x1F23A },
["japanese “passing grade” button"]={ 0x1F234 },
["japanese “prohibited” button"]={ 0x1F232 },
["japanese “reserved” button"]={ 0x1F22F },
- ["japanese “secret” button"]={ 0x3299 },
- ["japanese “service charge” button"]={ 0x1F202 },
+ ["japanese “secret” button"]={ 0x3299, 0xFE0F },
+ ["japanese “service charge” button"]={ 0x1F202, 0xFE0F },
["japanese “vacancy” button"]={ 0x1F233 },
["jeans"]={ 0x1F456 },
- ["jersey"]={ 0x1F1EF, 0x1F1EA },
["joker"]={ 0x1F0CF },
- ["jordan"]={ 0x1F1EF, 0x1F1F4 },
- ["joystick"]={ 0x1F579 },
+ ["joystick"]={ 0x1F579, 0xFE0F },
["kaaba"]={ 0x1F54B },
- ["kazakhstan"]={ 0x1F1F0, 0x1F1FF },
- ["kenya"]={ 0x1F1F0, 0x1F1EA },
+ ["kangaroo"]={ 0x1F998 },
["key"]={ 0x1F511 },
- ["keyboard"]={ 0x2328 },
- ["keycap 10"]={ 0x1F51F },
- ["keycap: 0"]={ 0x30, 0x20E3 },
- ["keycap: 1"]={ 0x31, 0x20E3 },
- ["keycap: 2"]={ 0x32, 0x20E3 },
- ["keycap: 3"]={ 0x33, 0x20E3 },
- ["keycap: 4"]={ 0x34, 0x20E3 },
- ["keycap: 5"]={ 0x35, 0x20E3 },
- ["keycap: 6"]={ 0x36, 0x20E3 },
- ["keycap: 7"]={ 0x37, 0x20E3 },
- ["keycap: 8"]={ 0x38, 0x20E3 },
- ["keycap: 9"]={ 0x39, 0x20E3 },
- ["keycap: asterisk"]={ 0x2A, 0x20E3 },
- ["keycap: hash"]={ 0x23, 0x20E3 },
+ ["keyboard"]={ 0x2328, 0xFE0F },
+ ["keycap: 0"]={ 0x30, 0xFE0F, 0x20E3 },
+ ["keycap: 1"]={ 0x31, 0xFE0F, 0x20E3 },
+ ["keycap: 10"]={ 0x1F51F },
+ ["keycap: 2"]={ 0x32, 0xFE0F, 0x20E3 },
+ ["keycap: 3"]={ 0x33, 0xFE0F, 0x20E3 },
+ ["keycap: 4"]={ 0x34, 0xFE0F, 0x20E3 },
+ ["keycap: 5"]={ 0x35, 0xFE0F, 0x20E3 },
+ ["keycap: 6"]={ 0x36, 0xFE0F, 0x20E3 },
+ ["keycap: 7"]={ 0x37, 0xFE0F, 0x20E3 },
+ ["keycap: 8"]={ 0x38, 0xFE0F, 0x20E3 },
+ ["keycap: 9"]={ 0x39, 0xFE0F, 0x20E3 },
+ ["keycap: asterisk"]={ 0x2A, 0xFE0F, 0x20E3 },
+ ["keycap: hash"]={ 0x23, 0xFE0F, 0x20E3 },
["kick scooter"]={ 0x1F6F4 },
["kimono"]={ 0x1F458 },
- ["kiribati"]={ 0x1F1F0, 0x1F1EE },
["kiss"]={ 0x1F48F },
["kiss mark"]={ 0x1F48B },
- ["kiss: man, man"]={ 0x1F468, 0x200D, 0x2764, 0x200D, 0x1F48B, 0x200D, 0x1F468 },
- ["kiss: woman, man"]={ 0x1F469, 0x200D, 0x2764, 0x200D, 0x1F48B, 0x200D, 0x1F468 },
- ["kiss: woman, woman"]={ 0x1F469, 0x200D, 0x2764, 0x200D, 0x1F48B, 0x200D, 0x1F469 },
- ["kissing cat face with closed eyes"]={ 0x1F63D },
+ ["kiss: man, man"]={ 0x1F468, 0x200D, 0x2764, 0xFE0F, 0x200D, 0x1F48B, 0x200D, 0x1F468 },
+ ["kiss: woman, man"]={ 0x1F469, 0x200D, 0x2764, 0xFE0F, 0x200D, 0x1F48B, 0x200D, 0x1F468 },
+ ["kiss: woman, woman"]={ 0x1F469, 0x200D, 0x2764, 0xFE0F, 0x200D, 0x1F48B, 0x200D, 0x1F469 },
+ ["kissing cat"]={ 0x1F63D },
["kissing face"]={ 0x1F617 },
["kissing face with closed eyes"]={ 0x1F61A },
["kissing face with smiling eyes"]={ 0x1F619 },
["kitchen knife"]={ 0x1F52A },
+ ["kite"]={ 0x1FA81 },
["kiwi fruit"]={ 0x1F95D },
["koala"]={ 0x1F428 },
- ["kosovo"]={ 0x1F1FD, 0x1F1F0 },
- ["kuwait"]={ 0x1F1F0, 0x1F1FC },
- ["kyrgyzstan"]={ 0x1F1F0, 0x1F1EC },
- ["label"]={ 0x1F3F7 },
+ ["lab coat"]={ 0x1F97C },
+ ["label"]={ 0x1F3F7, 0xFE0F },
+ ["lacrosse"]={ 0x1F94D },
["lady beetle"]={ 0x1F41E },
- ["laos"]={ 0x1F1F1, 0x1F1E6 },
["laptop computer"]={ 0x1F4BB },
["large blue diamond"]={ 0x1F537 },
["large orange diamond"]={ 0x1F536 },
["last quarter moon"]={ 0x1F317 },
- ["last quarter moon with face"]={ 0x1F31C },
- ["last track button"]={ 0x23EE },
- ["latin cross"]={ 0x271D },
- ["latvia"]={ 0x1F1F1, 0x1F1FB },
+ ["last quarter moon face"]={ 0x1F31C },
+ ["last track button"]={ 0x23EE, 0xFE0F },
+ ["latin cross"]={ 0x271D, 0xFE0F },
["leaf fluttering in wind"]={ 0x1F343 },
- ["lebanon"]={ 0x1F1F1, 0x1F1E7 },
+ ["leafy green"]={ 0x1F96C },
["ledger"]={ 0x1F4D2 },
- ["left arrow"]={ 0x2B05 },
- ["left arrow curving right"]={ 0x21AA },
+ ["left arrow"]={ 0x2B05, 0xFE0F },
+ ["left arrow curving right"]={ 0x21AA, 0xFE0F },
["left luggage"]={ 0x1F6C5 },
- ["left speech bubble"]={ 0x1F5E8 },
+ ["left speech bubble"]={ 0x1F5E8, 0xFE0F },
["left-facing fist"]={ 0x1F91B },
["left-facing fist: dark skin tone"]={ 0x1F91B, 0x1F3FF },
["left-facing fist: light skin tone"]={ 0x1F91B, 0x1F3FB },
["left-facing fist: medium skin tone"]={ 0x1F91B, 0x1F3FD },
["left-facing fist: medium-dark skin tone"]={ 0x1F91B, 0x1F3FE },
["left-facing fist: medium-light skin tone"]={ 0x1F91B, 0x1F3FC },
- ["left-pointing magnifying glass"]={ 0x1F50D },
- ["left-right arrow"]={ 0x2194 },
+ ["left-right arrow"]={ 0x2194, 0xFE0F },
+ ["leg"]={ 0x1F9B5 },
+ ["leg: dark skin tone"]={ 0x1F9B5, 0x1F3FF },
+ ["leg: light skin tone"]={ 0x1F9B5, 0x1F3FB },
+ ["leg: medium skin tone"]={ 0x1F9B5, 0x1F3FD },
+ ["leg: medium-dark skin tone"]={ 0x1F9B5, 0x1F3FE },
+ ["leg: medium-light skin tone"]={ 0x1F9B5, 0x1F3FC },
["lemon"]={ 0x1F34B },
["leo"]={ 0x264C },
["leopard"]={ 0x1F406 },
- ["lesotho"]={ 0x1F1F1, 0x1F1F8 },
- ["level slider"]={ 0x1F39A },
- ["liberia"]={ 0x1F1F1, 0x1F1F7 },
+ ["level slider"]={ 0x1F39A, 0xFE0F },
["libra"]={ 0x264E },
- ["libya"]={ 0x1F1F1, 0x1F1FE },
- ["liechtenstein"]={ 0x1F1F1, 0x1F1EE },
["light bulb"]={ 0x1F4A1 },
["light rail"]={ 0x1F688 },
["link"]={ 0x1F517 },
- ["linked paperclips"]={ 0x1F587 },
- ["lion face"]={ 0x1F981 },
+ ["linked paperclips"]={ 0x1F587, 0xFE0F },
+ ["lion"]={ 0x1F981 },
["lipstick"]={ 0x1F484 },
- ["lithuania"]={ 0x1F1F1, 0x1F1F9 },
["litter in bin sign"]={ 0x1F6AE },
["lizard"]={ 0x1F98E },
+ ["llama"]={ 0x1F999 },
+ ["lobster"]={ 0x1F99E },
["locked"]={ 0x1F512 },
["locked with key"]={ 0x1F510 },
["locked with pen"]={ 0x1F50F },
["locomotive"]={ 0x1F682 },
["lollipop"]={ 0x1F36D },
+ ["lotion bottle"]={ 0x1F9F4 },
["loudly crying face"]={ 0x1F62D },
["loudspeaker"]={ 0x1F4E2 },
["love hotel"]={ 0x1F3E9 },
@@ -918,26 +1110,20 @@ return {
["love-you gesture: medium skin tone"]={ 0x1F91F, 0x1F3FD },
["love-you gesture: medium-dark skin tone"]={ 0x1F91F, 0x1F3FE },
["love-you gesture: medium-light skin tone"]={ 0x1F91F, 0x1F3FC },
- ["luxembourg"]={ 0x1F1F1, 0x1F1FA },
+ ["luggage"]={ 0x1F9F3 },
["lying face"]={ 0x1F925 },
- ["macau sar china"]={ 0x1F1F2, 0x1F1F4 },
- ["macedonia"]={ 0x1F1F2, 0x1F1F0 },
- ["madagascar"]={ 0x1F1F2, 0x1F1EC },
["mage"]={ 0x1F9D9 },
["mage: dark skin tone"]={ 0x1F9D9, 0x1F3FF },
["mage: light skin tone"]={ 0x1F9D9, 0x1F3FB },
["mage: medium skin tone"]={ 0x1F9D9, 0x1F3FD },
["mage: medium-dark skin tone"]={ 0x1F9D9, 0x1F3FE },
["mage: medium-light skin tone"]={ 0x1F9D9, 0x1F3FC },
+ ["magnet"]={ 0x1F9F2 },
+ ["magnifying glass tilted left"]={ 0x1F50D },
+ ["magnifying glass tilted right"]={ 0x1F50E },
["mahjong red dragon"]={ 0x1F004 },
- ["malawi"]={ 0x1F1F2, 0x1F1FC },
- ["malaysia"]={ 0x1F1F2, 0x1F1FE },
- ["maldives"]={ 0x1F1F2, 0x1F1FB },
- ["male sign"]={ 0x2642 },
- ["mali"]={ 0x1F1F2, 0x1F1F1 },
- ["malta"]={ 0x1F1F2, 0x1F1F9 },
+ ["male sign"]={ 0x2642, 0xFE0F },
["man"]={ 0x1F468 },
- ["man and woman holding hands"]={ 0x1F46B },
["man artist"]={ 0x1F468, 0x200D, 0x1F3A8 },
["man artist: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F3A8 },
["man artist: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F3A8 },
@@ -950,42 +1136,42 @@ return {
["man astronaut: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F680 },
["man astronaut: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F680 },
["man astronaut: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F680 },
- ["man biking"]={ 0x1F6B4, 0x200D, 0x2642 },
- ["man biking: dark skin tone"]={ 0x1F6B4, 0x1F3FF, 0x200D, 0x2642 },
- ["man biking: light skin tone"]={ 0x1F6B4, 0x1F3FB, 0x200D, 0x2642 },
- ["man biking: medium skin tone"]={ 0x1F6B4, 0x1F3FD, 0x200D, 0x2642 },
- ["man biking: medium-dark skin tone"]={ 0x1F6B4, 0x1F3FE, 0x200D, 0x2642 },
- ["man biking: medium-light skin tone"]={ 0x1F6B4, 0x1F3FC, 0x200D, 0x2642 },
- ["man bouncing ball"]={ 0x26F9, 0x200D, 0x2642 },
- ["man bouncing ball: dark skin tone"]={ 0x26F9, 0x1F3FF, 0x200D, 0x2642 },
- ["man bouncing ball: light skin tone"]={ 0x26F9, 0x1F3FB, 0x200D, 0x2642 },
- ["man bouncing ball: medium skin tone"]={ 0x26F9, 0x1F3FD, 0x200D, 0x2642 },
- ["man bouncing ball: medium-dark skin tone"]={ 0x26F9, 0x1F3FE, 0x200D, 0x2642 },
- ["man bouncing ball: medium-light skin tone"]={ 0x26F9, 0x1F3FC, 0x200D, 0x2642 },
- ["man bowing"]={ 0x1F647, 0x200D, 0x2642 },
- ["man bowing: dark skin tone"]={ 0x1F647, 0x1F3FF, 0x200D, 0x2642 },
- ["man bowing: light skin tone"]={ 0x1F647, 0x1F3FB, 0x200D, 0x2642 },
- ["man bowing: medium skin tone"]={ 0x1F647, 0x1F3FD, 0x200D, 0x2642 },
- ["man bowing: medium-dark skin tone"]={ 0x1F647, 0x1F3FE, 0x200D, 0x2642 },
- ["man bowing: medium-light skin tone"]={ 0x1F647, 0x1F3FC, 0x200D, 0x2642 },
- ["man cartwheeling"]={ 0x1F938, 0x200D, 0x2642 },
- ["man cartwheeling: dark skin tone"]={ 0x1F938, 0x1F3FF, 0x200D, 0x2642 },
- ["man cartwheeling: light skin tone"]={ 0x1F938, 0x1F3FB, 0x200D, 0x2642 },
- ["man cartwheeling: medium skin tone"]={ 0x1F938, 0x1F3FD, 0x200D, 0x2642 },
- ["man cartwheeling: medium-dark skin tone"]={ 0x1F938, 0x1F3FE, 0x200D, 0x2642 },
- ["man cartwheeling: medium-light skin tone"]={ 0x1F938, 0x1F3FC, 0x200D, 0x2642 },
- ["man climbing"]={ 0x1F9D7, 0x200D, 0x2642 },
- ["man climbing: dark skin tone"]={ 0x1F9D7, 0x1F3FF, 0x200D, 0x2642 },
- ["man climbing: light skin tone"]={ 0x1F9D7, 0x1F3FB, 0x200D, 0x2642 },
- ["man climbing: medium skin tone"]={ 0x1F9D7, 0x1F3FD, 0x200D, 0x2642 },
- ["man climbing: medium-dark skin tone"]={ 0x1F9D7, 0x1F3FE, 0x200D, 0x2642 },
- ["man climbing: medium-light skin tone"]={ 0x1F9D7, 0x1F3FC, 0x200D, 0x2642 },
- ["man construction worker"]={ 0x1F477, 0x200D, 0x2642 },
- ["man construction worker: dark skin tone"]={ 0x1F477, 0x1F3FF, 0x200D, 0x2642 },
- ["man construction worker: light skin tone"]={ 0x1F477, 0x1F3FB, 0x200D, 0x2642 },
- ["man construction worker: medium skin tone"]={ 0x1F477, 0x1F3FD, 0x200D, 0x2642 },
- ["man construction worker: medium-dark skin tone"]={ 0x1F477, 0x1F3FE, 0x200D, 0x2642 },
- ["man construction worker: medium-light skin tone"]={ 0x1F477, 0x1F3FC, 0x200D, 0x2642 },
+ ["man biking"]={ 0x1F6B4, 0x200D, 0x2642, 0xFE0F },
+ ["man biking: dark skin tone"]={ 0x1F6B4, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man biking: light skin tone"]={ 0x1F6B4, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man biking: medium skin tone"]={ 0x1F6B4, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man biking: medium-dark skin tone"]={ 0x1F6B4, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man biking: medium-light skin tone"]={ 0x1F6B4, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man bouncing ball"]={ 0x26F9, 0xFE0F, 0x200D, 0x2642, 0xFE0F },
+ ["man bouncing ball: dark skin tone"]={ 0x26F9, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man bouncing ball: light skin tone"]={ 0x26F9, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man bouncing ball: medium skin tone"]={ 0x26F9, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man bouncing ball: medium-dark skin tone"]={ 0x26F9, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man bouncing ball: medium-light skin tone"]={ 0x26F9, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man bowing"]={ 0x1F647, 0x200D, 0x2642, 0xFE0F },
+ ["man bowing: dark skin tone"]={ 0x1F647, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man bowing: light skin tone"]={ 0x1F647, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man bowing: medium skin tone"]={ 0x1F647, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man bowing: medium-dark skin tone"]={ 0x1F647, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man bowing: medium-light skin tone"]={ 0x1F647, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man cartwheeling"]={ 0x1F938, 0x200D, 0x2642, 0xFE0F },
+ ["man cartwheeling: dark skin tone"]={ 0x1F938, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man cartwheeling: light skin tone"]={ 0x1F938, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man cartwheeling: medium skin tone"]={ 0x1F938, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man cartwheeling: medium-dark skin tone"]={ 0x1F938, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man cartwheeling: medium-light skin tone"]={ 0x1F938, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man climbing"]={ 0x1F9D7, 0x200D, 0x2642, 0xFE0F },
+ ["man climbing: dark skin tone"]={ 0x1F9D7, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man climbing: light skin tone"]={ 0x1F9D7, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man climbing: medium skin tone"]={ 0x1F9D7, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man climbing: medium-dark skin tone"]={ 0x1F9D7, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man climbing: medium-light skin tone"]={ 0x1F9D7, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man construction worker"]={ 0x1F477, 0x200D, 0x2642, 0xFE0F },
+ ["man construction worker: dark skin tone"]={ 0x1F477, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man construction worker: light skin tone"]={ 0x1F477, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man construction worker: medium skin tone"]={ 0x1F477, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man construction worker: medium-dark skin tone"]={ 0x1F477, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man construction worker: medium-light skin tone"]={ 0x1F477, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
["man cook"]={ 0x1F468, 0x200D, 0x1F373 },
["man cook: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F373 },
["man cook: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F373 },
@@ -998,36 +1184,36 @@ return {
["man dancing: medium skin tone"]={ 0x1F57A, 0x1F3FD },
["man dancing: medium-dark skin tone"]={ 0x1F57A, 0x1F3FE },
["man dancing: medium-light skin tone"]={ 0x1F57A, 0x1F3FC },
- ["man detective"]={ 0x1F575, 0x200D, 0x2642 },
- ["man detective: dark skin tone"]={ 0x1F575, 0x1F3FF, 0x200D, 0x2642 },
- ["man detective: light skin tone"]={ 0x1F575, 0x1F3FB, 0x200D, 0x2642 },
- ["man detective: medium skin tone"]={ 0x1F575, 0x1F3FD, 0x200D, 0x2642 },
- ["man detective: medium-dark skin tone"]={ 0x1F575, 0x1F3FE, 0x200D, 0x2642 },
- ["man detective: medium-light skin tone"]={ 0x1F575, 0x1F3FC, 0x200D, 0x2642 },
- ["man elf"]={ 0x1F9DD, 0x200D, 0x2642 },
- ["man elf: dark skin tone"]={ 0x1F9DD, 0x1F3FF, 0x200D, 0x2642 },
- ["man elf: light skin tone"]={ 0x1F9DD, 0x1F3FB, 0x200D, 0x2642 },
- ["man elf: medium skin tone"]={ 0x1F9DD, 0x1F3FD, 0x200D, 0x2642 },
- ["man elf: medium-dark skin tone"]={ 0x1F9DD, 0x1F3FE, 0x200D, 0x2642 },
- ["man elf: medium-light skin tone"]={ 0x1F9DD, 0x1F3FC, 0x200D, 0x2642 },
- ["man facepalming"]={ 0x1F926, 0x200D, 0x2642 },
- ["man facepalming: dark skin tone"]={ 0x1F926, 0x1F3FF, 0x200D, 0x2642 },
- ["man facepalming: light skin tone"]={ 0x1F926, 0x1F3FB, 0x200D, 0x2642 },
- ["man facepalming: medium skin tone"]={ 0x1F926, 0x1F3FD, 0x200D, 0x2642 },
- ["man facepalming: medium-dark skin tone"]={ 0x1F926, 0x1F3FE, 0x200D, 0x2642 },
- ["man facepalming: medium-light skin tone"]={ 0x1F926, 0x1F3FC, 0x200D, 0x2642 },
+ ["man detective"]={ 0x1F575, 0xFE0F, 0x200D, 0x2642, 0xFE0F },
+ ["man detective: dark skin tone"]={ 0x1F575, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man detective: light skin tone"]={ 0x1F575, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man detective: medium skin tone"]={ 0x1F575, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man detective: medium-dark skin tone"]={ 0x1F575, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man detective: medium-light skin tone"]={ 0x1F575, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man elf"]={ 0x1F9DD, 0x200D, 0x2642, 0xFE0F },
+ ["man elf: dark skin tone"]={ 0x1F9DD, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man elf: light skin tone"]={ 0x1F9DD, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man elf: medium skin tone"]={ 0x1F9DD, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man elf: medium-dark skin tone"]={ 0x1F9DD, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man elf: medium-light skin tone"]={ 0x1F9DD, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man facepalming"]={ 0x1F926, 0x200D, 0x2642, 0xFE0F },
+ ["man facepalming: dark skin tone"]={ 0x1F926, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man facepalming: light skin tone"]={ 0x1F926, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man facepalming: medium skin tone"]={ 0x1F926, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man facepalming: medium-dark skin tone"]={ 0x1F926, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man facepalming: medium-light skin tone"]={ 0x1F926, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
["man factory worker"]={ 0x1F468, 0x200D, 0x1F3ED },
["man factory worker: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F3ED },
["man factory worker: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F3ED },
["man factory worker: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F3ED },
["man factory worker: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F3ED },
["man factory worker: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F3ED },
- ["man fairy"]={ 0x1F9DA, 0x200D, 0x2642 },
- ["man fairy: dark skin tone"]={ 0x1F9DA, 0x1F3FF, 0x200D, 0x2642 },
- ["man fairy: light skin tone"]={ 0x1F9DA, 0x1F3FB, 0x200D, 0x2642 },
- ["man fairy: medium skin tone"]={ 0x1F9DA, 0x1F3FD, 0x200D, 0x2642 },
- ["man fairy: medium-dark skin tone"]={ 0x1F9DA, 0x1F3FE, 0x200D, 0x2642 },
- ["man fairy: medium-light skin tone"]={ 0x1F9DA, 0x1F3FC, 0x200D, 0x2642 },
+ ["man fairy"]={ 0x1F9DA, 0x200D, 0x2642, 0xFE0F },
+ ["man fairy: dark skin tone"]={ 0x1F9DA, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man fairy: light skin tone"]={ 0x1F9DA, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man fairy: medium skin tone"]={ 0x1F9DA, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man fairy: medium-dark skin tone"]={ 0x1F9DA, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man fairy: medium-light skin tone"]={ 0x1F9DA, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
["man farmer"]={ 0x1F468, 0x200D, 0x1F33E },
["man farmer: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F33E },
["man farmer: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F33E },
@@ -1040,205 +1226,241 @@ return {
["man firefighter: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F692 },
["man firefighter: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F692 },
["man firefighter: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F692 },
- ["man frowning"]={ 0x1F64D, 0x200D, 0x2642 },
- ["man frowning: dark skin tone"]={ 0x1F64D, 0x1F3FF, 0x200D, 0x2642 },
- ["man frowning: light skin tone"]={ 0x1F64D, 0x1F3FB, 0x200D, 0x2642 },
- ["man frowning: medium skin tone"]={ 0x1F64D, 0x1F3FD, 0x200D, 0x2642 },
- ["man frowning: medium-dark skin tone"]={ 0x1F64D, 0x1F3FE, 0x200D, 0x2642 },
- ["man frowning: medium-light skin tone"]={ 0x1F64D, 0x1F3FC, 0x200D, 0x2642 },
- ["man genie"]={ 0x1F9DE, 0x200D, 0x2642 },
- ["man gesturing no"]={ 0x1F645, 0x200D, 0x2642 },
- ["man gesturing no: dark skin tone"]={ 0x1F645, 0x1F3FF, 0x200D, 0x2642 },
- ["man gesturing no: light skin tone"]={ 0x1F645, 0x1F3FB, 0x200D, 0x2642 },
- ["man gesturing no: medium skin tone"]={ 0x1F645, 0x1F3FD, 0x200D, 0x2642 },
- ["man gesturing no: medium-dark skin tone"]={ 0x1F645, 0x1F3FE, 0x200D, 0x2642 },
- ["man gesturing no: medium-light skin tone"]={ 0x1F645, 0x1F3FC, 0x200D, 0x2642 },
- ["man gesturing ok"]={ 0x1F646, 0x200D, 0x2642 },
- ["man gesturing ok: dark skin tone"]={ 0x1F646, 0x1F3FF, 0x200D, 0x2642 },
- ["man gesturing ok: light skin tone"]={ 0x1F646, 0x1F3FB, 0x200D, 0x2642 },
- ["man gesturing ok: medium skin tone"]={ 0x1F646, 0x1F3FD, 0x200D, 0x2642 },
- ["man gesturing ok: medium-dark skin tone"]={ 0x1F646, 0x1F3FE, 0x200D, 0x2642 },
- ["man gesturing ok: medium-light skin tone"]={ 0x1F646, 0x1F3FC, 0x200D, 0x2642 },
- ["man getting haircut"]={ 0x1F487, 0x200D, 0x2642 },
- ["man getting haircut: dark skin tone"]={ 0x1F487, 0x1F3FF, 0x200D, 0x2642 },
- ["man getting haircut: light skin tone"]={ 0x1F487, 0x1F3FB, 0x200D, 0x2642 },
- ["man getting haircut: medium skin tone"]={ 0x1F487, 0x1F3FD, 0x200D, 0x2642 },
- ["man getting haircut: medium-dark skin tone"]={ 0x1F487, 0x1F3FE, 0x200D, 0x2642 },
- ["man getting haircut: medium-light skin tone"]={ 0x1F487, 0x1F3FC, 0x200D, 0x2642 },
- ["man getting massage"]={ 0x1F486, 0x200D, 0x2642 },
- ["man getting massage: dark skin tone"]={ 0x1F486, 0x1F3FF, 0x200D, 0x2642 },
- ["man getting massage: light skin tone"]={ 0x1F486, 0x1F3FB, 0x200D, 0x2642 },
- ["man getting massage: medium skin tone"]={ 0x1F486, 0x1F3FD, 0x200D, 0x2642 },
- ["man getting massage: medium-dark skin tone"]={ 0x1F486, 0x1F3FE, 0x200D, 0x2642 },
- ["man getting massage: medium-light skin tone"]={ 0x1F486, 0x1F3FC, 0x200D, 0x2642 },
- ["man golfing"]={ 0x1F3CC, 0x200D, 0x2642 },
- ["man golfing: dark skin tone"]={ 0x1F3CC, 0x1F3FF, 0x200D, 0x2642 },
- ["man golfing: light skin tone"]={ 0x1F3CC, 0x1F3FB, 0x200D, 0x2642 },
- ["man golfing: medium skin tone"]={ 0x1F3CC, 0x1F3FD, 0x200D, 0x2642 },
- ["man golfing: medium-dark skin tone"]={ 0x1F3CC, 0x1F3FE, 0x200D, 0x2642 },
- ["man golfing: medium-light skin tone"]={ 0x1F3CC, 0x1F3FC, 0x200D, 0x2642 },
- ["man guard"]={ 0x1F482, 0x200D, 0x2642 },
- ["man guard: dark skin tone"]={ 0x1F482, 0x1F3FF, 0x200D, 0x2642 },
- ["man guard: light skin tone"]={ 0x1F482, 0x1F3FB, 0x200D, 0x2642 },
- ["man guard: medium skin tone"]={ 0x1F482, 0x1F3FD, 0x200D, 0x2642 },
- ["man guard: medium-dark skin tone"]={ 0x1F482, 0x1F3FE, 0x200D, 0x2642 },
- ["man guard: medium-light skin tone"]={ 0x1F482, 0x1F3FC, 0x200D, 0x2642 },
- ["man health worker"]={ 0x1F468, 0x200D, 0x2695 },
- ["man health worker: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2695 },
- ["man health worker: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2695 },
- ["man health worker: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x2695 },
- ["man health worker: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x2695 },
- ["man health worker: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x2695 },
- ["man in business suit levitating"]={ 0x1F574 },
- ["man in business suit levitating: dark skin tone"]={ 0x1F574, 0x1F3FF },
- ["man in business suit levitating: light skin tone"]={ 0x1F574, 0x1F3FB },
- ["man in business suit levitating: medium skin tone"]={ 0x1F574, 0x1F3FD },
- ["man in business suit levitating: medium-dark skin tone"]={ 0x1F574, 0x1F3FE },
- ["man in business suit levitating: medium-light skin tone"]={ 0x1F574, 0x1F3FC },
- ["man in lotus position"]={ 0x1F9D8, 0x200D, 0x2642 },
- ["man in lotus position: dark skin tone"]={ 0x1F9D8, 0x1F3FF, 0x200D, 0x2642 },
- ["man in lotus position: light skin tone"]={ 0x1F9D8, 0x1F3FB, 0x200D, 0x2642 },
- ["man in lotus position: medium skin tone"]={ 0x1F9D8, 0x1F3FD, 0x200D, 0x2642 },
- ["man in lotus position: medium-dark skin tone"]={ 0x1F9D8, 0x1F3FE, 0x200D, 0x2642 },
- ["man in lotus position: medium-light skin tone"]={ 0x1F9D8, 0x1F3FC, 0x200D, 0x2642 },
- ["man in steamy room"]={ 0x1F9D6, 0x200D, 0x2642 },
- ["man in steamy room: dark skin tone"]={ 0x1F9D6, 0x1F3FF, 0x200D, 0x2642 },
- ["man in steamy room: light skin tone"]={ 0x1F9D6, 0x1F3FB, 0x200D, 0x2642 },
- ["man in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD, 0x200D, 0x2642 },
- ["man in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE, 0x200D, 0x2642 },
- ["man in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC, 0x200D, 0x2642 },
+ ["man frowning"]={ 0x1F64D, 0x200D, 0x2642, 0xFE0F },
+ ["man frowning: dark skin tone"]={ 0x1F64D, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man frowning: light skin tone"]={ 0x1F64D, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man frowning: medium skin tone"]={ 0x1F64D, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man frowning: medium-dark skin tone"]={ 0x1F64D, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man frowning: medium-light skin tone"]={ 0x1F64D, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man genie"]={ 0x1F9DE, 0x200D, 0x2642, 0xFE0F },
+ ["man gesturing no"]={ 0x1F645, 0x200D, 0x2642, 0xFE0F },
+ ["man gesturing no: dark skin tone"]={ 0x1F645, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man gesturing no: light skin tone"]={ 0x1F645, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man gesturing no: medium skin tone"]={ 0x1F645, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man gesturing no: medium-dark skin tone"]={ 0x1F645, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man gesturing no: medium-light skin tone"]={ 0x1F645, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man gesturing ok"]={ 0x1F646, 0x200D, 0x2642, 0xFE0F },
+ ["man gesturing ok: dark skin tone"]={ 0x1F646, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man gesturing ok: light skin tone"]={ 0x1F646, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man gesturing ok: medium skin tone"]={ 0x1F646, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man gesturing ok: medium-dark skin tone"]={ 0x1F646, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man gesturing ok: medium-light skin tone"]={ 0x1F646, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man getting haircut"]={ 0x1F487, 0x200D, 0x2642, 0xFE0F },
+ ["man getting haircut: dark skin tone"]={ 0x1F487, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man getting haircut: light skin tone"]={ 0x1F487, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man getting haircut: medium skin tone"]={ 0x1F487, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man getting haircut: medium-dark skin tone"]={ 0x1F487, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man getting haircut: medium-light skin tone"]={ 0x1F487, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man getting massage"]={ 0x1F486, 0x200D, 0x2642, 0xFE0F },
+ ["man getting massage: dark skin tone"]={ 0x1F486, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man getting massage: light skin tone"]={ 0x1F486, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man getting massage: medium skin tone"]={ 0x1F486, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man getting massage: medium-dark skin tone"]={ 0x1F486, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man getting massage: medium-light skin tone"]={ 0x1F486, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man golfing"]={ 0x1F3CC, 0xFE0F, 0x200D, 0x2642, 0xFE0F },
+ ["man golfing: dark skin tone"]={ 0x1F3CC, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man golfing: light skin tone"]={ 0x1F3CC, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man golfing: medium skin tone"]={ 0x1F3CC, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man golfing: medium-dark skin tone"]={ 0x1F3CC, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man golfing: medium-light skin tone"]={ 0x1F3CC, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man guard"]={ 0x1F482, 0x200D, 0x2642, 0xFE0F },
+ ["man guard: dark skin tone"]={ 0x1F482, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man guard: light skin tone"]={ 0x1F482, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man guard: medium skin tone"]={ 0x1F482, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man guard: medium-dark skin tone"]={ 0x1F482, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man guard: medium-light skin tone"]={ 0x1F482, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man health worker"]={ 0x1F468, 0x200D, 0x2695, 0xFE0F },
+ ["man health worker: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2695, 0xFE0F },
+ ["man health worker: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2695, 0xFE0F },
+ ["man health worker: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x2695, 0xFE0F },
+ ["man health worker: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x2695, 0xFE0F },
+ ["man health worker: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x2695, 0xFE0F },
+ ["man in lotus position"]={ 0x1F9D8, 0x200D, 0x2642, 0xFE0F },
+ ["man in lotus position: dark skin tone"]={ 0x1F9D8, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man in lotus position: light skin tone"]={ 0x1F9D8, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man in lotus position: medium skin tone"]={ 0x1F9D8, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man in lotus position: medium-dark skin tone"]={ 0x1F9D8, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man in lotus position: medium-light skin tone"]={ 0x1F9D8, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man in manual wheelchair"]={ 0x1F468, 0x200D, 0x1F9BD },
+ ["man in manual wheelchair: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9BD },
+ ["man in manual wheelchair: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9BD },
+ ["man in manual wheelchair: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9BD },
+ ["man in manual wheelchair: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9BD },
+ ["man in manual wheelchair: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9BD },
+ ["man in motorized wheelchair"]={ 0x1F468, 0x200D, 0x1F9BC },
+ ["man in motorized wheelchair: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9BC },
+ ["man in motorized wheelchair: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9BC },
+ ["man in motorized wheelchair: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9BC },
+ ["man in motorized wheelchair: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9BC },
+ ["man in motorized wheelchair: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9BC },
+ ["man in steamy room"]={ 0x1F9D6, 0x200D, 0x2642, 0xFE0F },
+ ["man in steamy room: dark skin tone"]={ 0x1F9D6, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man in steamy room: light skin tone"]={ 0x1F9D6, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man in suit levitating"]={ 0x1F574, 0xFE0F },
+ ["man in suit levitating: dark skin tone"]={ 0x1F574, 0x1F3FF },
+ ["man in suit levitating: light skin tone"]={ 0x1F574, 0x1F3FB },
+ ["man in suit levitating: medium skin tone"]={ 0x1F574, 0x1F3FD },
+ ["man in suit levitating: medium-dark skin tone"]={ 0x1F574, 0x1F3FE },
+ ["man in suit levitating: medium-light skin tone"]={ 0x1F574, 0x1F3FC },
["man in tuxedo"]={ 0x1F935 },
["man in tuxedo: dark skin tone"]={ 0x1F935, 0x1F3FF },
["man in tuxedo: light skin tone"]={ 0x1F935, 0x1F3FB },
["man in tuxedo: medium skin tone"]={ 0x1F935, 0x1F3FD },
["man in tuxedo: medium-dark skin tone"]={ 0x1F935, 0x1F3FE },
["man in tuxedo: medium-light skin tone"]={ 0x1F935, 0x1F3FC },
- ["man judge"]={ 0x1F468, 0x200D, 0x2696 },
- ["man judge: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2696 },
- ["man judge: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2696 },
- ["man judge: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x2696 },
- ["man judge: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x2696 },
- ["man judge: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x2696 },
- ["man juggling"]={ 0x1F939, 0x200D, 0x2642 },
- ["man juggling: dark skin tone"]={ 0x1F939, 0x1F3FF, 0x200D, 0x2642 },
- ["man juggling: light skin tone"]={ 0x1F939, 0x1F3FB, 0x200D, 0x2642 },
- ["man juggling: medium skin tone"]={ 0x1F939, 0x1F3FD, 0x200D, 0x2642 },
- ["man juggling: medium-dark skin tone"]={ 0x1F939, 0x1F3FE, 0x200D, 0x2642 },
- ["man juggling: medium-light skin tone"]={ 0x1F939, 0x1F3FC, 0x200D, 0x2642 },
- ["man lifting weights"]={ 0x1F3CB, 0x200D, 0x2642 },
- ["man lifting weights: dark skin tone"]={ 0x1F3CB, 0x1F3FF, 0x200D, 0x2642 },
- ["man lifting weights: light skin tone"]={ 0x1F3CB, 0x1F3FB, 0x200D, 0x2642 },
- ["man lifting weights: medium skin tone"]={ 0x1F3CB, 0x1F3FD, 0x200D, 0x2642 },
- ["man lifting weights: medium-dark skin tone"]={ 0x1F3CB, 0x1F3FE, 0x200D, 0x2642 },
- ["man lifting weights: medium-light skin tone"]={ 0x1F3CB, 0x1F3FC, 0x200D, 0x2642 },
- ["man mage"]={ 0x1F9D9, 0x200D, 0x2642 },
- ["man mage: dark skin tone"]={ 0x1F9D9, 0x1F3FF, 0x200D, 0x2642 },
- ["man mage: light skin tone"]={ 0x1F9D9, 0x1F3FB, 0x200D, 0x2642 },
- ["man mage: medium skin tone"]={ 0x1F9D9, 0x1F3FD, 0x200D, 0x2642 },
- ["man mage: medium-dark skin tone"]={ 0x1F9D9, 0x1F3FE, 0x200D, 0x2642 },
- ["man mage: medium-light skin tone"]={ 0x1F9D9, 0x1F3FC, 0x200D, 0x2642 },
+ ["man judge"]={ 0x1F468, 0x200D, 0x2696, 0xFE0F },
+ ["man judge: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2696, 0xFE0F },
+ ["man judge: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2696, 0xFE0F },
+ ["man judge: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x2696, 0xFE0F },
+ ["man judge: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x2696, 0xFE0F },
+ ["man judge: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x2696, 0xFE0F },
+ ["man juggling"]={ 0x1F939, 0x200D, 0x2642, 0xFE0F },
+ ["man juggling: dark skin tone"]={ 0x1F939, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man juggling: light skin tone"]={ 0x1F939, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man juggling: medium skin tone"]={ 0x1F939, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man juggling: medium-dark skin tone"]={ 0x1F939, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man juggling: medium-light skin tone"]={ 0x1F939, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man kneeling"]={ 0x1F9CE, 0x200D, 0x2642, 0xFE0F },
+ ["man kneeling: dark skin tone"]={ 0x1F9CE, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man kneeling: light skin tone"]={ 0x1F9CE, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man kneeling: medium skin tone"]={ 0x1F9CE, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man kneeling: medium-dark skin tone"]={ 0x1F9CE, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man kneeling: medium-light skin tone"]={ 0x1F9CE, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man lifting weights"]={ 0x1F3CB, 0xFE0F, 0x200D, 0x2642, 0xFE0F },
+ ["man lifting weights: dark skin tone"]={ 0x1F3CB, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man lifting weights: light skin tone"]={ 0x1F3CB, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man lifting weights: medium skin tone"]={ 0x1F3CB, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man lifting weights: medium-dark skin tone"]={ 0x1F3CB, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man lifting weights: medium-light skin tone"]={ 0x1F3CB, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man mage"]={ 0x1F9D9, 0x200D, 0x2642, 0xFE0F },
+ ["man mage: dark skin tone"]={ 0x1F9D9, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man mage: light skin tone"]={ 0x1F9D9, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man mage: medium skin tone"]={ 0x1F9D9, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man mage: medium-dark skin tone"]={ 0x1F9D9, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man mage: medium-light skin tone"]={ 0x1F9D9, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
["man mechanic"]={ 0x1F468, 0x200D, 0x1F527 },
["man mechanic: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F527 },
["man mechanic: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F527 },
["man mechanic: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F527 },
["man mechanic: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F527 },
["man mechanic: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F527 },
- ["man mountain biking"]={ 0x1F6B5, 0x200D, 0x2642 },
- ["man mountain biking: dark skin tone"]={ 0x1F6B5, 0x1F3FF, 0x200D, 0x2642 },
- ["man mountain biking: light skin tone"]={ 0x1F6B5, 0x1F3FB, 0x200D, 0x2642 },
- ["man mountain biking: medium skin tone"]={ 0x1F6B5, 0x1F3FD, 0x200D, 0x2642 },
- ["man mountain biking: medium-dark skin tone"]={ 0x1F6B5, 0x1F3FE, 0x200D, 0x2642 },
- ["man mountain biking: medium-light skin tone"]={ 0x1F6B5, 0x1F3FC, 0x200D, 0x2642 },
+ ["man mountain biking"]={ 0x1F6B5, 0x200D, 0x2642, 0xFE0F },
+ ["man mountain biking: dark skin tone"]={ 0x1F6B5, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man mountain biking: light skin tone"]={ 0x1F6B5, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man mountain biking: medium skin tone"]={ 0x1F6B5, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man mountain biking: medium-dark skin tone"]={ 0x1F6B5, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man mountain biking: medium-light skin tone"]={ 0x1F6B5, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
["man office worker"]={ 0x1F468, 0x200D, 0x1F4BC },
["man office worker: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F4BC },
["man office worker: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F4BC },
["man office worker: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F4BC },
["man office worker: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F4BC },
["man office worker: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F4BC },
- ["man pilot"]={ 0x1F468, 0x200D, 0x2708 },
- ["man pilot: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2708 },
- ["man pilot: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2708 },
- ["man pilot: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x2708 },
- ["man pilot: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x2708 },
- ["man pilot: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x2708 },
- ["man playing handball"]={ 0x1F93E, 0x200D, 0x2642 },
- ["man playing handball: dark skin tone"]={ 0x1F93E, 0x1F3FF, 0x200D, 0x2642 },
- ["man playing handball: light skin tone"]={ 0x1F93E, 0x1F3FB, 0x200D, 0x2642 },
- ["man playing handball: medium skin tone"]={ 0x1F93E, 0x1F3FD, 0x200D, 0x2642 },
- ["man playing handball: medium-dark skin tone"]={ 0x1F93E, 0x1F3FE, 0x200D, 0x2642 },
- ["man playing handball: medium-light skin tone"]={ 0x1F93E, 0x1F3FC, 0x200D, 0x2642 },
- ["man playing water polo"]={ 0x1F93D, 0x200D, 0x2642 },
- ["man playing water polo: dark skin tone"]={ 0x1F93D, 0x1F3FF, 0x200D, 0x2642 },
- ["man playing water polo: light skin tone"]={ 0x1F93D, 0x1F3FB, 0x200D, 0x2642 },
- ["man playing water polo: medium skin tone"]={ 0x1F93D, 0x1F3FD, 0x200D, 0x2642 },
- ["man playing water polo: medium-dark skin tone"]={ 0x1F93D, 0x1F3FE, 0x200D, 0x2642 },
- ["man playing water polo: medium-light skin tone"]={ 0x1F93D, 0x1F3FC, 0x200D, 0x2642 },
- ["man police officer"]={ 0x1F46E, 0x200D, 0x2642 },
- ["man police officer: dark skin tone"]={ 0x1F46E, 0x1F3FF, 0x200D, 0x2642 },
- ["man police officer: light skin tone"]={ 0x1F46E, 0x1F3FB, 0x200D, 0x2642 },
- ["man police officer: medium skin tone"]={ 0x1F46E, 0x1F3FD, 0x200D, 0x2642 },
- ["man police officer: medium-dark skin tone"]={ 0x1F46E, 0x1F3FE, 0x200D, 0x2642 },
- ["man police officer: medium-light skin tone"]={ 0x1F46E, 0x1F3FC, 0x200D, 0x2642 },
- ["man pouting"]={ 0x1F64E, 0x200D, 0x2642 },
- ["man pouting: dark skin tone"]={ 0x1F64E, 0x1F3FF, 0x200D, 0x2642 },
- ["man pouting: light skin tone"]={ 0x1F64E, 0x1F3FB, 0x200D, 0x2642 },
- ["man pouting: medium skin tone"]={ 0x1F64E, 0x1F3FD, 0x200D, 0x2642 },
- ["man pouting: medium-dark skin tone"]={ 0x1F64E, 0x1F3FE, 0x200D, 0x2642 },
- ["man pouting: medium-light skin tone"]={ 0x1F64E, 0x1F3FC, 0x200D, 0x2642 },
- ["man raising hand"]={ 0x1F64B, 0x200D, 0x2642 },
- ["man raising hand: dark skin tone"]={ 0x1F64B, 0x1F3FF, 0x200D, 0x2642 },
- ["man raising hand: light skin tone"]={ 0x1F64B, 0x1F3FB, 0x200D, 0x2642 },
- ["man raising hand: medium skin tone"]={ 0x1F64B, 0x1F3FD, 0x200D, 0x2642 },
- ["man raising hand: medium-dark skin tone"]={ 0x1F64B, 0x1F3FE, 0x200D, 0x2642 },
- ["man raising hand: medium-light skin tone"]={ 0x1F64B, 0x1F3FC, 0x200D, 0x2642 },
- ["man rowing boat"]={ 0x1F6A3, 0x200D, 0x2642 },
- ["man rowing boat: dark skin tone"]={ 0x1F6A3, 0x1F3FF, 0x200D, 0x2642 },
- ["man rowing boat: light skin tone"]={ 0x1F6A3, 0x1F3FB, 0x200D, 0x2642 },
- ["man rowing boat: medium skin tone"]={ 0x1F6A3, 0x1F3FD, 0x200D, 0x2642 },
- ["man rowing boat: medium-dark skin tone"]={ 0x1F6A3, 0x1F3FE, 0x200D, 0x2642 },
- ["man rowing boat: medium-light skin tone"]={ 0x1F6A3, 0x1F3FC, 0x200D, 0x2642 },
- ["man running"]={ 0x1F3C3, 0x200D, 0x2642 },
- ["man running: dark skin tone"]={ 0x1F3C3, 0x1F3FF, 0x200D, 0x2642 },
- ["man running: light skin tone"]={ 0x1F3C3, 0x1F3FB, 0x200D, 0x2642 },
- ["man running: medium skin tone"]={ 0x1F3C3, 0x1F3FD, 0x200D, 0x2642 },
- ["man running: medium-dark skin tone"]={ 0x1F3C3, 0x1F3FE, 0x200D, 0x2642 },
- ["man running: medium-light skin tone"]={ 0x1F3C3, 0x1F3FC, 0x200D, 0x2642 },
+ ["man pilot"]={ 0x1F468, 0x200D, 0x2708, 0xFE0F },
+ ["man pilot: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x2708, 0xFE0F },
+ ["man pilot: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x2708, 0xFE0F },
+ ["man pilot: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x2708, 0xFE0F },
+ ["man pilot: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x2708, 0xFE0F },
+ ["man pilot: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x2708, 0xFE0F },
+ ["man playing handball"]={ 0x1F93E, 0x200D, 0x2642, 0xFE0F },
+ ["man playing handball: dark skin tone"]={ 0x1F93E, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man playing handball: light skin tone"]={ 0x1F93E, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man playing handball: medium skin tone"]={ 0x1F93E, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man playing handball: medium-dark skin tone"]={ 0x1F93E, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man playing handball: medium-light skin tone"]={ 0x1F93E, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man playing water polo"]={ 0x1F93D, 0x200D, 0x2642, 0xFE0F },
+ ["man playing water polo: dark skin tone"]={ 0x1F93D, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man playing water polo: light skin tone"]={ 0x1F93D, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man playing water polo: medium skin tone"]={ 0x1F93D, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man playing water polo: medium-dark skin tone"]={ 0x1F93D, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man playing water polo: medium-light skin tone"]={ 0x1F93D, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man police officer"]={ 0x1F46E, 0x200D, 0x2642, 0xFE0F },
+ ["man police officer: dark skin tone"]={ 0x1F46E, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man police officer: light skin tone"]={ 0x1F46E, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man police officer: medium skin tone"]={ 0x1F46E, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man police officer: medium-dark skin tone"]={ 0x1F46E, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man police officer: medium-light skin tone"]={ 0x1F46E, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man pouting"]={ 0x1F64E, 0x200D, 0x2642, 0xFE0F },
+ ["man pouting: dark skin tone"]={ 0x1F64E, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man pouting: light skin tone"]={ 0x1F64E, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man pouting: medium skin tone"]={ 0x1F64E, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man pouting: medium-dark skin tone"]={ 0x1F64E, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man pouting: medium-light skin tone"]={ 0x1F64E, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man raising hand"]={ 0x1F64B, 0x200D, 0x2642, 0xFE0F },
+ ["man raising hand: dark skin tone"]={ 0x1F64B, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man raising hand: light skin tone"]={ 0x1F64B, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man raising hand: medium skin tone"]={ 0x1F64B, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man raising hand: medium-dark skin tone"]={ 0x1F64B, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man raising hand: medium-light skin tone"]={ 0x1F64B, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man rowing boat"]={ 0x1F6A3, 0x200D, 0x2642, 0xFE0F },
+ ["man rowing boat: dark skin tone"]={ 0x1F6A3, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man rowing boat: light skin tone"]={ 0x1F6A3, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man rowing boat: medium skin tone"]={ 0x1F6A3, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man rowing boat: medium-dark skin tone"]={ 0x1F6A3, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man rowing boat: medium-light skin tone"]={ 0x1F6A3, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man running"]={ 0x1F3C3, 0x200D, 0x2642, 0xFE0F },
+ ["man running: dark skin tone"]={ 0x1F3C3, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man running: light skin tone"]={ 0x1F3C3, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man running: medium skin tone"]={ 0x1F3C3, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man running: medium-dark skin tone"]={ 0x1F3C3, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man running: medium-light skin tone"]={ 0x1F3C3, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
["man scientist"]={ 0x1F468, 0x200D, 0x1F52C },
["man scientist: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F52C },
["man scientist: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F52C },
["man scientist: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F52C },
["man scientist: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F52C },
["man scientist: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F52C },
- ["man shrugging"]={ 0x1F937, 0x200D, 0x2642 },
- ["man shrugging: dark skin tone"]={ 0x1F937, 0x1F3FF, 0x200D, 0x2642 },
- ["man shrugging: light skin tone"]={ 0x1F937, 0x1F3FB, 0x200D, 0x2642 },
- ["man shrugging: medium skin tone"]={ 0x1F937, 0x1F3FD, 0x200D, 0x2642 },
- ["man shrugging: medium-dark skin tone"]={ 0x1F937, 0x1F3FE, 0x200D, 0x2642 },
- ["man shrugging: medium-light skin tone"]={ 0x1F937, 0x1F3FC, 0x200D, 0x2642 },
+ ["man shrugging"]={ 0x1F937, 0x200D, 0x2642, 0xFE0F },
+ ["man shrugging: dark skin tone"]={ 0x1F937, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man shrugging: light skin tone"]={ 0x1F937, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man shrugging: medium skin tone"]={ 0x1F937, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man shrugging: medium-dark skin tone"]={ 0x1F937, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man shrugging: medium-light skin tone"]={ 0x1F937, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
["man singer"]={ 0x1F468, 0x200D, 0x1F3A4 },
["man singer: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F3A4 },
["man singer: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F3A4 },
["man singer: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F3A4 },
["man singer: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F3A4 },
["man singer: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F3A4 },
+ ["man standing"]={ 0x1F9CD, 0x200D, 0x2642, 0xFE0F },
+ ["man standing: dark skin tone"]={ 0x1F9CD, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man standing: light skin tone"]={ 0x1F9CD, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man standing: medium skin tone"]={ 0x1F9CD, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man standing: medium-dark skin tone"]={ 0x1F9CD, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man standing: medium-light skin tone"]={ 0x1F9CD, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
["man student"]={ 0x1F468, 0x200D, 0x1F393 },
["man student: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F393 },
["man student: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F393 },
["man student: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F393 },
["man student: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F393 },
["man student: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F393 },
- ["man surfing"]={ 0x1F3C4, 0x200D, 0x2642 },
- ["man surfing: dark skin tone"]={ 0x1F3C4, 0x1F3FF, 0x200D, 0x2642 },
- ["man surfing: light skin tone"]={ 0x1F3C4, 0x1F3FB, 0x200D, 0x2642 },
- ["man surfing: medium skin tone"]={ 0x1F3C4, 0x1F3FD, 0x200D, 0x2642 },
- ["man surfing: medium-dark skin tone"]={ 0x1F3C4, 0x1F3FE, 0x200D, 0x2642 },
- ["man surfing: medium-light skin tone"]={ 0x1F3C4, 0x1F3FC, 0x200D, 0x2642 },
- ["man swimming"]={ 0x1F3CA, 0x200D, 0x2642 },
- ["man swimming: dark skin tone"]={ 0x1F3CA, 0x1F3FF, 0x200D, 0x2642 },
- ["man swimming: light skin tone"]={ 0x1F3CA, 0x1F3FB, 0x200D, 0x2642 },
- ["man swimming: medium skin tone"]={ 0x1F3CA, 0x1F3FD, 0x200D, 0x2642 },
- ["man swimming: medium-dark skin tone"]={ 0x1F3CA, 0x1F3FE, 0x200D, 0x2642 },
- ["man swimming: medium-light skin tone"]={ 0x1F3CA, 0x1F3FC, 0x200D, 0x2642 },
+ ["man superhero"]={ 0x1F9B8, 0x200D, 0x2642, 0xFE0F },
+ ["man superhero: dark skin tone"]={ 0x1F9B8, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man superhero: light skin tone"]={ 0x1F9B8, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man superhero: medium skin tone"]={ 0x1F9B8, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man superhero: medium-dark skin tone"]={ 0x1F9B8, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man superhero: medium-light skin tone"]={ 0x1F9B8, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man supervillain"]={ 0x1F9B9, 0x200D, 0x2642, 0xFE0F },
+ ["man supervillain: dark skin tone"]={ 0x1F9B9, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man supervillain: light skin tone"]={ 0x1F9B9, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man supervillain: medium skin tone"]={ 0x1F9B9, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man supervillain: medium-dark skin tone"]={ 0x1F9B9, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man supervillain: medium-light skin tone"]={ 0x1F9B9, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man surfing"]={ 0x1F3C4, 0x200D, 0x2642, 0xFE0F },
+ ["man surfing: dark skin tone"]={ 0x1F3C4, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man surfing: light skin tone"]={ 0x1F3C4, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man surfing: medium skin tone"]={ 0x1F3C4, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man surfing: medium-dark skin tone"]={ 0x1F3C4, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man surfing: medium-light skin tone"]={ 0x1F3C4, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man swimming"]={ 0x1F3CA, 0x200D, 0x2642, 0xFE0F },
+ ["man swimming: dark skin tone"]={ 0x1F3CA, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man swimming: light skin tone"]={ 0x1F3CA, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man swimming: medium skin tone"]={ 0x1F3CA, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man swimming: medium-dark skin tone"]={ 0x1F3CA, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man swimming: medium-light skin tone"]={ 0x1F3CA, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
["man teacher"]={ 0x1F468, 0x200D, 0x1F3EB },
["man teacher: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F3EB },
["man teacher: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F3EB },
@@ -1251,73 +1473,131 @@ return {
["man technologist: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F4BB },
["man technologist: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F4BB },
["man technologist: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F4BB },
- ["man tipping hand"]={ 0x1F481, 0x200D, 0x2642 },
- ["man tipping hand: dark skin tone"]={ 0x1F481, 0x1F3FF, 0x200D, 0x2642 },
- ["man tipping hand: light skin tone"]={ 0x1F481, 0x1F3FB, 0x200D, 0x2642 },
- ["man tipping hand: medium skin tone"]={ 0x1F481, 0x1F3FD, 0x200D, 0x2642 },
- ["man tipping hand: medium-dark skin tone"]={ 0x1F481, 0x1F3FE, 0x200D, 0x2642 },
- ["man tipping hand: medium-light skin tone"]={ 0x1F481, 0x1F3FC, 0x200D, 0x2642 },
- ["man vampire"]={ 0x1F9DB, 0x200D, 0x2642 },
- ["man vampire: dark skin tone"]={ 0x1F9DB, 0x1F3FF, 0x200D, 0x2642 },
- ["man vampire: light skin tone"]={ 0x1F9DB, 0x1F3FB, 0x200D, 0x2642 },
- ["man vampire: medium skin tone"]={ 0x1F9DB, 0x1F3FD, 0x200D, 0x2642 },
- ["man vampire: medium-dark skin tone"]={ 0x1F9DB, 0x1F3FE, 0x200D, 0x2642 },
- ["man vampire: medium-light skin tone"]={ 0x1F9DB, 0x1F3FC, 0x200D, 0x2642 },
- ["man walking"]={ 0x1F6B6, 0x200D, 0x2642 },
- ["man walking: dark skin tone"]={ 0x1F6B6, 0x1F3FF, 0x200D, 0x2642 },
- ["man walking: light skin tone"]={ 0x1F6B6, 0x1F3FB, 0x200D, 0x2642 },
- ["man walking: medium skin tone"]={ 0x1F6B6, 0x1F3FD, 0x200D, 0x2642 },
- ["man walking: medium-dark skin tone"]={ 0x1F6B6, 0x1F3FE, 0x200D, 0x2642 },
- ["man walking: medium-light skin tone"]={ 0x1F6B6, 0x1F3FC, 0x200D, 0x2642 },
- ["man wearing turban"]={ 0x1F473, 0x200D, 0x2642 },
- ["man wearing turban: dark skin tone"]={ 0x1F473, 0x1F3FF, 0x200D, 0x2642 },
- ["man wearing turban: light skin tone"]={ 0x1F473, 0x1F3FB, 0x200D, 0x2642 },
- ["man wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD, 0x200D, 0x2642 },
- ["man wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE, 0x200D, 0x2642 },
- ["man wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC, 0x200D, 0x2642 },
+ ["man tipping hand"]={ 0x1F481, 0x200D, 0x2642, 0xFE0F },
+ ["man tipping hand: dark skin tone"]={ 0x1F481, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man tipping hand: light skin tone"]={ 0x1F481, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man tipping hand: medium skin tone"]={ 0x1F481, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man tipping hand: medium-dark skin tone"]={ 0x1F481, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man tipping hand: medium-light skin tone"]={ 0x1F481, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man vampire"]={ 0x1F9DB, 0x200D, 0x2642, 0xFE0F },
+ ["man vampire: dark skin tone"]={ 0x1F9DB, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man vampire: light skin tone"]={ 0x1F9DB, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man vampire: medium skin tone"]={ 0x1F9DB, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man vampire: medium-dark skin tone"]={ 0x1F9DB, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man vampire: medium-light skin tone"]={ 0x1F9DB, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man walking"]={ 0x1F6B6, 0x200D, 0x2642, 0xFE0F },
+ ["man walking: dark skin tone"]={ 0x1F6B6, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man walking: light skin tone"]={ 0x1F6B6, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man walking: medium skin tone"]={ 0x1F6B6, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man walking: medium-dark skin tone"]={ 0x1F6B6, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man walking: medium-light skin tone"]={ 0x1F6B6, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man wearing turban"]={ 0x1F473, 0x200D, 0x2642, 0xFE0F },
+ ["man wearing turban: dark skin tone"]={ 0x1F473, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man wearing turban: light skin tone"]={ 0x1F473, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
["man with chinese cap"]={ 0x1F472 },
["man with chinese cap: dark skin tone"]={ 0x1F472, 0x1F3FF },
["man with chinese cap: light skin tone"]={ 0x1F472, 0x1F3FB },
["man with chinese cap: medium skin tone"]={ 0x1F472, 0x1F3FD },
["man with chinese cap: medium-dark skin tone"]={ 0x1F472, 0x1F3FE },
["man with chinese cap: medium-light skin tone"]={ 0x1F472, 0x1F3FC },
- ["man zombie"]={ 0x1F9DF, 0x200D, 0x2642 },
+ ["man with probing cane"]={ 0x1F468, 0x200D, 0x1F9AF },
+ ["man with probing cane: dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9AF },
+ ["man with probing cane: light skin tone"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9AF },
+ ["man with probing cane: medium skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9AF },
+ ["man with probing cane: medium-dark skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9AF },
+ ["man with probing cane: medium-light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9AF },
+ ["man zombie"]={ 0x1F9DF, 0x200D, 0x2642, 0xFE0F },
+ ["man: bald"]={ 0x1F468, 0x200D, 0x1F9B2 },
+ ["man: beard"]={ 0x1F9D4 },
+ ["man: blond hair"]={ 0x1F471, 0x200D, 0x2642, 0xFE0F },
+ ["man: curly hair"]={ 0x1F468, 0x200D, 0x1F9B1 },
["man: dark skin tone"]={ 0x1F468, 0x1F3FF },
+ ["man: dark skin tone, bald"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9B2 },
+ ["man: dark skin tone, beard"]={ 0x1F9D4, 0x1F3FF },
+ ["man: dark skin tone, blond hair"]={ 0x1F471, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["man: dark skin tone, curly hair"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9B1 },
+ ["man: dark skin tone, red hair"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9B0 },
+ ["man: dark skin tone, white hair"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F9B3 },
["man: light skin tone"]={ 0x1F468, 0x1F3FB },
+ ["man: light skin tone, bald"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9B2 },
+ ["man: light skin tone, beard"]={ 0x1F9D4, 0x1F3FB },
+ ["man: light skin tone, blond hair"]={ 0x1F471, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["man: light skin tone, curly hair"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9B1 },
+ ["man: light skin tone, red hair"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9B0 },
+ ["man: light skin tone, white hair"]={ 0x1F468, 0x1F3FB, 0x200D, 0x1F9B3 },
["man: medium skin tone"]={ 0x1F468, 0x1F3FD },
+ ["man: medium skin tone, bald"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9B2 },
+ ["man: medium skin tone, beard"]={ 0x1F9D4, 0x1F3FD },
+ ["man: medium skin tone, blond hair"]={ 0x1F471, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["man: medium skin tone, curly hair"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9B1 },
+ ["man: medium skin tone, red hair"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9B0 },
+ ["man: medium skin tone, white hair"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F9B3 },
["man: medium-dark skin tone"]={ 0x1F468, 0x1F3FE },
+ ["man: medium-dark skin tone, bald"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9B2 },
+ ["man: medium-dark skin tone, beard"]={ 0x1F9D4, 0x1F3FE },
+ ["man: medium-dark skin tone, blond hair"]={ 0x1F471, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["man: medium-dark skin tone, curly hair"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9B1 },
+ ["man: medium-dark skin tone, red hair"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9B0 },
+ ["man: medium-dark skin tone, white hair"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F9B3 },
["man: medium-light skin tone"]={ 0x1F468, 0x1F3FC },
- ["mantelpiece clock"]={ 0x1F570 },
+ ["man: medium-light skin tone, bald"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9B2 },
+ ["man: medium-light skin tone, beard"]={ 0x1F9D4, 0x1F3FC },
+ ["man: medium-light skin tone, blond hair"]={ 0x1F471, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
+ ["man: medium-light skin tone, curly hair"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9B1 },
+ ["man: medium-light skin tone, red hair"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9B0 },
+ ["man: medium-light skin tone, white hair"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F9B3 },
+ ["man: red hair"]={ 0x1F468, 0x200D, 0x1F9B0 },
+ ["man: white hair"]={ 0x1F468, 0x200D, 0x1F9B3 },
+ ["mango"]={ 0x1F96D },
+ ["mantelpiece clock"]={ 0x1F570, 0xFE0F },
+ ["manual wheelchair"]={ 0x1F9BD },
["man’s shoe"]={ 0x1F45E },
["map of japan"]={ 0x1F5FE },
["maple leaf"]={ 0x1F341 },
- ["marshall islands"]={ 0x1F1F2, 0x1F1ED },
["martial arts uniform"]={ 0x1F94B },
- ["martinique"]={ 0x1F1F2, 0x1F1F6 },
- ["mauritania"]={ 0x1F1F2, 0x1F1F7 },
- ["mauritius"]={ 0x1F1F2, 0x1F1FA },
- ["mayotte"]={ 0x1F1FE, 0x1F1F9 },
+ ["mate"]={ 0x1F9C9 },
["meat on bone"]={ 0x1F356 },
- ["medical symbol"]={ 0x2695 },
+ ["mechanical arm"]={ 0x1F9BE },
+ ["mechanical leg"]={ 0x1F9BF },
+ ["medical symbol"]={ 0x2695, 0xFE0F },
["megaphone"]={ 0x1F4E3 },
["melon"]={ 0x1F348 },
["memo"]={ 0x1F4DD },
- ["men with bunny ears partying"]={ 0x1F46F, 0x200D, 0x2642 },
- ["men wrestling"]={ 0x1F93C, 0x200D, 0x2642 },
+ ["men holding hands"]={ 0x1F46C },
+ ["men holding hands: dark skin tone"]={ 0x1F46C, 0x1F3FF },
+ ["men holding hands: dark skin tone, light skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB },
+ ["men holding hands: dark skin tone, medium skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD },
+ ["men holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE },
+ ["men holding hands: dark skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC },
+ ["men holding hands: light skin tone"]={ 0x1F46C, 0x1F3FB },
+ ["men holding hands: medium skin tone"]={ 0x1F46C, 0x1F3FD },
+ ["men holding hands: medium skin tone, light skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB },
+ ["men holding hands: medium skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC },
+ ["men holding hands: medium-dark skin tone"]={ 0x1F46C, 0x1F3FE },
+ ["men holding hands: medium-dark skin tone, light skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB },
+ ["men holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD },
+ ["men holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F468, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC },
+ ["men holding hands: medium-light skin tone"]={ 0x1F46C, 0x1F3FC },
+ ["men holding hands: medium-light skin tone, light skin tone"]={ 0x1F468, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB },
+ ["men with bunny ears"]={ 0x1F46F, 0x200D, 0x2642, 0xFE0F },
+ ["men wrestling"]={ 0x1F93C, 0x200D, 0x2642, 0xFE0F },
["menorah"]={ 0x1F54E },
["men’s room"]={ 0x1F6B9 },
- ["mermaid"]={ 0x1F9DC, 0x200D, 0x2640 },
- ["mermaid: dark skin tone"]={ 0x1F9DC, 0x1F3FF, 0x200D, 0x2640 },
- ["mermaid: light skin tone"]={ 0x1F9DC, 0x1F3FB, 0x200D, 0x2640 },
- ["mermaid: medium skin tone"]={ 0x1F9DC, 0x1F3FD, 0x200D, 0x2640 },
- ["mermaid: medium-dark skin tone"]={ 0x1F9DC, 0x1F3FE, 0x200D, 0x2640 },
- ["mermaid: medium-light skin tone"]={ 0x1F9DC, 0x1F3FC, 0x200D, 0x2640 },
- ["merman"]={ 0x1F9DC, 0x200D, 0x2642 },
- ["merman: dark skin tone"]={ 0x1F9DC, 0x1F3FF, 0x200D, 0x2642 },
- ["merman: light skin tone"]={ 0x1F9DC, 0x1F3FB, 0x200D, 0x2642 },
- ["merman: medium skin tone"]={ 0x1F9DC, 0x1F3FD, 0x200D, 0x2642 },
- ["merman: medium-dark skin tone"]={ 0x1F9DC, 0x1F3FE, 0x200D, 0x2642 },
- ["merman: medium-light skin tone"]={ 0x1F9DC, 0x1F3FC, 0x200D, 0x2642 },
+ ["mermaid"]={ 0x1F9DC, 0x200D, 0x2640, 0xFE0F },
+ ["mermaid: dark skin tone"]={ 0x1F9DC, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["mermaid: light skin tone"]={ 0x1F9DC, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["mermaid: medium skin tone"]={ 0x1F9DC, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["mermaid: medium-dark skin tone"]={ 0x1F9DC, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["mermaid: medium-light skin tone"]={ 0x1F9DC, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["merman"]={ 0x1F9DC, 0x200D, 0x2642, 0xFE0F },
+ ["merman: dark skin tone"]={ 0x1F9DC, 0x1F3FF, 0x200D, 0x2642, 0xFE0F },
+ ["merman: light skin tone"]={ 0x1F9DC, 0x1F3FB, 0x200D, 0x2642, 0xFE0F },
+ ["merman: medium skin tone"]={ 0x1F9DC, 0x1F3FD, 0x200D, 0x2642, 0xFE0F },
+ ["merman: medium-dark skin tone"]={ 0x1F9DC, 0x1F3FE, 0x200D, 0x2642, 0xFE0F },
+ ["merman: medium-light skin tone"]={ 0x1F9DC, 0x1F3FC, 0x200D, 0x2642, 0xFE0F },
["merperson"]={ 0x1F9DC },
["merperson: dark skin tone"]={ 0x1F9DC, 0x1F3FF },
["merperson: light skin tone"]={ 0x1F9DC, 0x1F3FB },
@@ -1325,8 +1605,7 @@ return {
["merperson: medium-dark skin tone"]={ 0x1F9DC, 0x1F3FE },
["merperson: medium-light skin tone"]={ 0x1F9DC, 0x1F3FC },
["metro"]={ 0x1F687 },
- ["mexico"]={ 0x1F1F2, 0x1F1FD },
- ["micronesia"]={ 0x1F1EB, 0x1F1F2 },
+ ["microbe"]={ 0x1F9A0 },
["microphone"]={ 0x1F3A4 },
["microscope"]={ 0x1F52C },
["middle finger"]={ 0x1F595 },
@@ -1335,53 +1614,50 @@ return {
["middle finger: medium skin tone"]={ 0x1F595, 0x1F3FD },
["middle finger: medium-dark skin tone"]={ 0x1F595, 0x1F3FE },
["middle finger: medium-light skin tone"]={ 0x1F595, 0x1F3FC },
- ["military medal"]={ 0x1F396 },
+ ["military medal"]={ 0x1F396, 0xFE0F },
["milky way"]={ 0x1F30C },
["minibus"]={ 0x1F690 },
+ ["minus sign"]={ 0x2796 },
["moai"]={ 0x1F5FF },
["mobile phone"]={ 0x1F4F1 },
["mobile phone off"]={ 0x1F4F4 },
["mobile phone with arrow"]={ 0x1F4F2 },
- ["moldova"]={ 0x1F1F2, 0x1F1E9 },
- ["monaco"]={ 0x1F1F2, 0x1F1E8 },
["money bag"]={ 0x1F4B0 },
["money with wings"]={ 0x1F4B8 },
["money-mouth face"]={ 0x1F911 },
- ["mongolia"]={ 0x1F1F2, 0x1F1F3 },
["monkey"]={ 0x1F412 },
["monkey face"]={ 0x1F435 },
["monorail"]={ 0x1F69D },
- ["montenegro"]={ 0x1F1F2, 0x1F1EA },
- ["montserrat"]={ 0x1F1F2, 0x1F1F8 },
+ ["moon cake"]={ 0x1F96E },
["moon viewing ceremony"]={ 0x1F391 },
- ["morocco"]={ 0x1F1F2, 0x1F1E6 },
["mosque"]={ 0x1F54C },
- ["motor boat"]={ 0x1F6E5 },
+ ["mosquito"]={ 0x1F99F },
+ ["motor boat"]={ 0x1F6E5, 0xFE0F },
["motor scooter"]={ 0x1F6F5 },
- ["motorcycle"]={ 0x1F3CD },
- ["motorway"]={ 0x1F6E3 },
+ ["motorcycle"]={ 0x1F3CD, 0xFE0F },
+ ["motorized wheelchair"]={ 0x1F9BC },
+ ["motorway"]={ 0x1F6E3, 0xFE0F },
["mount fuji"]={ 0x1F5FB },
- ["mountain"]={ 0x26F0 },
+ ["mountain"]={ 0x26F0, 0xFE0F },
["mountain cableway"]={ 0x1F6A0 },
["mountain railway"]={ 0x1F69E },
["mouse"]={ 0x1F401 },
["mouse face"]={ 0x1F42D },
["mouth"]={ 0x1F444 },
["movie camera"]={ 0x1F3A5 },
- ["mozambique"]={ 0x1F1F2, 0x1F1FF },
["mrs. claus"]={ 0x1F936 },
["mrs. claus: dark skin tone"]={ 0x1F936, 0x1F3FF },
["mrs. claus: light skin tone"]={ 0x1F936, 0x1F3FB },
["mrs. claus: medium skin tone"]={ 0x1F936, 0x1F3FD },
["mrs. claus: medium-dark skin tone"]={ 0x1F936, 0x1F3FE },
["mrs. claus: medium-light skin tone"]={ 0x1F936, 0x1F3FC },
+ ["multiplication sign"]={ 0x2716, 0xFE0F },
["mushroom"]={ 0x1F344 },
["musical keyboard"]={ 0x1F3B9 },
["musical note"]={ 0x1F3B5 },
["musical notes"]={ 0x1F3B6 },
["musical score"]={ 0x1F3BC },
["muted speaker"]={ 0x1F507 },
- ["myanmar (burma)"]={ 0x1F1F2, 0x1F1F2 },
["nail polish"]={ 0x1F485 },
["nail polish: dark skin tone"]={ 0x1F485, 0x1F3FF },
["nail polish: light skin tone"]={ 0x1F485, 0x1F3FB },
@@ -1389,30 +1665,21 @@ return {
["nail polish: medium-dark skin tone"]={ 0x1F485, 0x1F3FE },
["nail polish: medium-light skin tone"]={ 0x1F485, 0x1F3FC },
["name badge"]={ 0x1F4DB },
- ["namibia"]={ 0x1F1F3, 0x1F1E6 },
- ["national park"]={ 0x1F3DE },
- ["nauru"]={ 0x1F1F3, 0x1F1F7 },
+ ["national park"]={ 0x1F3DE, 0xFE0F },
["nauseated face"]={ 0x1F922 },
+ ["nazar amulet"]={ 0x1F9FF },
["necktie"]={ 0x1F454 },
- ["nepal"]={ 0x1F1F3, 0x1F1F5 },
["nerd face"]={ 0x1F913 },
- ["netherlands"]={ 0x1F1F3, 0x1F1F1 },
["neutral face"]={ 0x1F610 },
["new button"]={ 0x1F195 },
- ["new caledonia"]={ 0x1F1F3, 0x1F1E8 },
["new moon"]={ 0x1F311 },
["new moon face"]={ 0x1F31A },
- ["new zealand"]={ 0x1F1F3, 0x1F1FF },
["newspaper"]={ 0x1F4F0 },
- ["next track button"]={ 0x23ED },
+ ["next track button"]={ 0x23ED, 0xFE0F },
["ng button"]={ 0x1F196 },
- ["nicaragua"]={ 0x1F1F3, 0x1F1EE },
- ["niger"]={ 0x1F1F3, 0x1F1EA },
- ["nigeria"]={ 0x1F1F3, 0x1F1EC },
["night with stars"]={ 0x1F303 },
["nine o’clock"]={ 0x1F558 },
["nine-thirty"]={ 0x1F564 },
- ["niue"]={ 0x1F1F3, 0x1F1FA },
["no bicycles"]={ 0x1F6B3 },
["no entry"]={ 0x26D4 },
["no littering"]={ 0x1F6AF },
@@ -1421,10 +1688,6 @@ return {
["no pedestrians"]={ 0x1F6B7 },
["no smoking"]={ 0x1F6AD },
["non-potable water"]={ 0x1F6B1 },
- ["norfolk island"]={ 0x1F1F3, 0x1F1EB },
- ["north korea"]={ 0x1F1F0, 0x1F1F5 },
- ["northern mariana islands"]={ 0x1F1F2, 0x1F1F5 },
- ["norway"]={ 0x1F1F3, 0x1F1F4 },
["nose"]={ 0x1F443 },
["nose: dark skin tone"]={ 0x1F443, 0x1F3FF },
["nose: light skin tone"]={ 0x1F443, 0x1F3FB },
@@ -1434,12 +1697,12 @@ return {
["notebook"]={ 0x1F4D3 },
["notebook with decorative cover"]={ 0x1F4D4 },
["nut and bolt"]={ 0x1F529 },
- ["o button (blood type)"]={ 0x1F17E },
+ ["o button (blood type)"]={ 0x1F17E, 0xFE0F },
["octopus"]={ 0x1F419 },
["oden"]={ 0x1F362 },
["office building"]={ 0x1F3E2 },
["ogre"]={ 0x1F479 },
- ["oil drum"]={ 0x1F6E2 },
+ ["oil drum"]={ 0x1F6E2, 0xFE0F },
["ok button"]={ 0x1F197 },
["ok hand"]={ 0x1F44C },
["ok hand: dark skin tone"]={ 0x1F44C, 0x1F3FF },
@@ -1447,7 +1710,7 @@ return {
["ok hand: medium skin tone"]={ 0x1F44C, 0x1F3FD },
["ok hand: medium-dark skin tone"]={ 0x1F44C, 0x1F3FE },
["ok hand: medium-light skin tone"]={ 0x1F44C, 0x1F3FC },
- ["old key"]={ 0x1F5DD },
+ ["old key"]={ 0x1F5DD, 0xFE0F },
["old man"]={ 0x1F474 },
["old man: dark skin tone"]={ 0x1F474, 0x1F3FF },
["old man: light skin tone"]={ 0x1F474, 0x1F3FB },
@@ -1460,14 +1723,13 @@ return {
["old woman: medium skin tone"]={ 0x1F475, 0x1F3FD },
["old woman: medium-dark skin tone"]={ 0x1F475, 0x1F3FE },
["old woman: medium-light skin tone"]={ 0x1F475, 0x1F3FC },
- ["older adult"]={ 0x1F9D3 },
- ["older adult: dark skin tone"]={ 0x1F9D3, 0x1F3FF },
- ["older adult: light skin tone"]={ 0x1F9D3, 0x1F3FB },
- ["older adult: medium skin tone"]={ 0x1F9D3, 0x1F3FD },
- ["older adult: medium-dark skin tone"]={ 0x1F9D3, 0x1F3FE },
- ["older adult: medium-light skin tone"]={ 0x1F9D3, 0x1F3FC },
- ["om"]={ 0x1F549 },
- ["oman"]={ 0x1F1F4, 0x1F1F2 },
+ ["older person"]={ 0x1F9D3 },
+ ["older person: dark skin tone"]={ 0x1F9D3, 0x1F3FF },
+ ["older person: light skin tone"]={ 0x1F9D3, 0x1F3FB },
+ ["older person: medium skin tone"]={ 0x1F9D3, 0x1F3FD },
+ ["older person: medium-dark skin tone"]={ 0x1F9D3, 0x1F3FE },
+ ["older person: medium-light skin tone"]={ 0x1F9D3, 0x1F3FC },
+ ["om"]={ 0x1F549, 0xFE0F },
["on! arrow"]={ 0x1F51B },
["oncoming automobile"]={ 0x1F698 },
["oncoming bus"]={ 0x1F68D },
@@ -1480,7 +1742,9 @@ return {
["oncoming police car"]={ 0x1F694 },
["oncoming taxi"]={ 0x1F696 },
["one o’clock"]={ 0x1F550 },
+ ["one-piece swimsuit"]={ 0x1FA71 },
["one-thirty"]={ 0x1F55C },
+ ["onion"]={ 0x1F9C5 },
["open book"]={ 0x1F4D6 },
["open file folder"]={ 0x1F4C2 },
["open hands"]={ 0x1F450 },
@@ -1494,20 +1758,22 @@ return {
["ophiuchus"]={ 0x26CE },
["optical disk"]={ 0x1F4BF },
["orange book"]={ 0x1F4D9 },
+ ["orange circle"]={ 0x1F7E0 },
["orange heart"]={ 0x1F9E1 },
- ["orthodox cross"]={ 0x2626 },
+ ["orange square"]={ 0x1F7E7 },
+ ["orangutan"]={ 0x1F9A7 },
+ ["orthodox cross"]={ 0x2626, 0xFE0F },
+ ["otter"]={ 0x1F9A6 },
["outbox tray"]={ 0x1F4E4 },
["owl"]={ 0x1F989 },
["ox"]={ 0x1F402 },
- ["p button"]={ 0x1F17F },
+ ["oyster"]={ 0x1F9AA },
+ ["p button"]={ 0x1F17F, 0xFE0F },
["package"]={ 0x1F4E6 },
["page facing up"]={ 0x1F4C4 },
["page with curl"]={ 0x1F4C3 },
["pager"]={ 0x1F4DF },
- ["paintbrush"]={ 0x1F58C },
- ["pakistan"]={ 0x1F1F5, 0x1F1F0 },
- ["palau"]={ 0x1F1F5, 0x1F1FC },
- ["palestinian territories"]={ 0x1F1F5, 0x1F1F8 },
+ ["paintbrush"]={ 0x1F58C, 0xFE0F },
["palm tree"]={ 0x1F334 },
["palms up together"]={ 0x1F932 },
["palms up together: dark skin tone"]={ 0x1F932, 0x1F3FF },
@@ -1515,37 +1781,55 @@ return {
["palms up together: medium skin tone"]={ 0x1F932, 0x1F3FD },
["palms up together: medium-dark skin tone"]={ 0x1F932, 0x1F3FE },
["palms up together: medium-light skin tone"]={ 0x1F932, 0x1F3FC },
- ["panama"]={ 0x1F1F5, 0x1F1E6 },
["pancakes"]={ 0x1F95E },
- ["panda face"]={ 0x1F43C },
+ ["panda"]={ 0x1F43C },
["paperclip"]={ 0x1F4CE },
- ["papua new guinea"]={ 0x1F1F5, 0x1F1EC },
- ["paraguay"]={ 0x1F1F5, 0x1F1FE },
- ["part alternation mark"]={ 0x303D },
+ ["parachute"]={ 0x1FA82 },
+ ["parrot"]={ 0x1F99C },
+ ["part alternation mark"]={ 0x303D, 0xFE0F },
["party popper"]={ 0x1F389 },
- ["passenger ship"]={ 0x1F6F3 },
+ ["partying face"]={ 0x1F973 },
+ ["passenger ship"]={ 0x1F6F3, 0xFE0F },
["passport control"]={ 0x1F6C2 },
- ["pause button"]={ 0x23F8 },
+ ["pause button"]={ 0x23F8, 0xFE0F },
["paw prints"]={ 0x1F43E },
- ["peace symbol"]={ 0x262E },
+ ["peace symbol"]={ 0x262E, 0xFE0F },
["peach"]={ 0x1F351 },
+ ["peacock"]={ 0x1F99A },
["peanuts"]={ 0x1F95C },
["pear"]={ 0x1F350 },
- ["pen"]={ 0x1F58A },
- ["pencil"]={ 0x270F },
+ ["pen"]={ 0x1F58A, 0xFE0F },
+ ["pencil"]={ 0x270F, 0xFE0F },
["penguin"]={ 0x1F427 },
["pensive face"]={ 0x1F614 },
- ["people with bunny ears partying"]={ 0x1F46F },
+ ["people holding hands"]={ 0x1F9D1, 0x200D, 0x1F91D, 0x200D, 0x1F9D1 },
+ ["people holding hands: dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FF },
+ ["people holding hands: dark skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB },
+ ["people holding hands: dark skin tone, medium skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD },
+ ["people holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE },
+ ["people holding hands: dark skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC },
+ ["people holding hands: light skin tone"]={ 0x1F9D1, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB },
+ ["people holding hands: medium skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD },
+ ["people holding hands: medium skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB },
+ ["people holding hands: medium skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC },
+ ["people holding hands: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FE },
+ ["people holding hands: medium-dark skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB },
+ ["people holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FD },
+ ["people holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F9D1, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC },
+ ["people holding hands: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FC },
+ ["people holding hands: medium-light skin tone, light skin tone"]={ 0x1F9D1, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F9D1, 0x1F3FB },
+ ["people with bunny ears"]={ 0x1F46F },
["people wrestling"]={ 0x1F93C },
["performing arts"]={ 0x1F3AD },
["persevering face"]={ 0x1F623 },
+ ["person"]={ 0x1F9D1 },
["person biking"]={ 0x1F6B4 },
["person biking: dark skin tone"]={ 0x1F6B4, 0x1F3FF },
["person biking: light skin tone"]={ 0x1F6B4, 0x1F3FB },
["person biking: medium skin tone"]={ 0x1F6B4, 0x1F3FD },
["person biking: medium-dark skin tone"]={ 0x1F6B4, 0x1F3FE },
["person biking: medium-light skin tone"]={ 0x1F6B4, 0x1F3FC },
- ["person bouncing ball"]={ 0x26F9 },
+ ["person bouncing ball"]={ 0x26F9, 0xFE0F },
["person bouncing ball: dark skin tone"]={ 0x26F9, 0x1F3FF },
["person bouncing ball: light skin tone"]={ 0x26F9, 0x1F3FB },
["person bouncing ball: medium skin tone"]={ 0x26F9, 0x1F3FD },
@@ -1606,7 +1890,7 @@ return {
["person getting massage: medium skin tone"]={ 0x1F486, 0x1F3FD },
["person getting massage: medium-dark skin tone"]={ 0x1F486, 0x1F3FE },
["person getting massage: medium-light skin tone"]={ 0x1F486, 0x1F3FC },
- ["person golfing"]={ 0x1F3CC },
+ ["person golfing"]={ 0x1F3CC, 0xFE0F },
["person golfing: dark skin tone"]={ 0x1F3CC, 0x1F3FF },
["person golfing: light skin tone"]={ 0x1F3CC, 0x1F3FB },
["person golfing: medium skin tone"]={ 0x1F3CC, 0x1F3FD },
@@ -1636,7 +1920,13 @@ return {
["person juggling: medium skin tone"]={ 0x1F939, 0x1F3FD },
["person juggling: medium-dark skin tone"]={ 0x1F939, 0x1F3FE },
["person juggling: medium-light skin tone"]={ 0x1F939, 0x1F3FC },
- ["person lifting weights"]={ 0x1F3CB },
+ ["person kneeling"]={ 0x1F9CE },
+ ["person kneeling: dark skin tone"]={ 0x1F9CE, 0x1F3FF },
+ ["person kneeling: light skin tone"]={ 0x1F9CE, 0x1F3FB },
+ ["person kneeling: medium skin tone"]={ 0x1F9CE, 0x1F3FD },
+ ["person kneeling: medium-dark skin tone"]={ 0x1F9CE, 0x1F3FE },
+ ["person kneeling: medium-light skin tone"]={ 0x1F9CE, 0x1F3FC },
+ ["person lifting weights"]={ 0x1F3CB, 0xFE0F },
["person lifting weights: dark skin tone"]={ 0x1F3CB, 0x1F3FF },
["person lifting weights: light skin tone"]={ 0x1F3CB, 0x1F3FB },
["person lifting weights: medium skin tone"]={ 0x1F3CB, 0x1F3FD },
@@ -1690,6 +1980,12 @@ return {
["person shrugging: medium skin tone"]={ 0x1F937, 0x1F3FD },
["person shrugging: medium-dark skin tone"]={ 0x1F937, 0x1F3FE },
["person shrugging: medium-light skin tone"]={ 0x1F937, 0x1F3FC },
+ ["person standing"]={ 0x1F9CD },
+ ["person standing: dark skin tone"]={ 0x1F9CD, 0x1F3FF },
+ ["person standing: light skin tone"]={ 0x1F9CD, 0x1F3FB },
+ ["person standing: medium skin tone"]={ 0x1F9CD, 0x1F3FD },
+ ["person standing: medium-dark skin tone"]={ 0x1F9CD, 0x1F3FE },
+ ["person standing: medium-light skin tone"]={ 0x1F9CD, 0x1F3FC },
["person surfing"]={ 0x1F3C4 },
["person surfing: dark skin tone"]={ 0x1F3C4, 0x1F3FF },
["person surfing: light skin tone"]={ 0x1F3C4, 0x1F3FB },
@@ -1726,26 +2022,43 @@ return {
["person wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD },
["person wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE },
["person wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC },
- ["peru"]={ 0x1F1F5, 0x1F1EA },
- ["philippines"]={ 0x1F1F5, 0x1F1ED },
- ["pick"]={ 0x26CF },
+ ["person: blond hair"]={ 0x1F471 },
+ ["person: dark skin tone"]={ 0x1F9D1, 0x1F3FF },
+ ["person: dark skin tone, blond hair"]={ 0x1F471, 0x1F3FF },
+ ["person: light skin tone"]={ 0x1F9D1, 0x1F3FB },
+ ["person: light skin tone, blond hair"]={ 0x1F471, 0x1F3FB },
+ ["person: medium skin tone"]={ 0x1F9D1, 0x1F3FD },
+ ["person: medium skin tone, blond hair"]={ 0x1F471, 0x1F3FD },
+ ["person: medium-dark skin tone"]={ 0x1F9D1, 0x1F3FE },
+ ["person: medium-dark skin tone, blond hair"]={ 0x1F471, 0x1F3FE },
+ ["person: medium-light skin tone"]={ 0x1F9D1, 0x1F3FC },
+ ["person: medium-light skin tone, blond hair"]={ 0x1F471, 0x1F3FC },
+ ["petri dish"]={ 0x1F9EB },
+ ["pick"]={ 0x26CF, 0xFE0F },
["pie"]={ 0x1F967 },
["pig"]={ 0x1F416 },
["pig face"]={ 0x1F437 },
["pig nose"]={ 0x1F43D },
["pile of poo"]={ 0x1F4A9 },
["pill"]={ 0x1F48A },
+ ["pinching hand"]={ 0x1F90F },
+ ["pinching hand: dark skin tone"]={ 0x1F90F, 0x1F3FF },
+ ["pinching hand: light skin tone"]={ 0x1F90F, 0x1F3FB },
+ ["pinching hand: medium skin tone"]={ 0x1F90F, 0x1F3FD },
+ ["pinching hand: medium-dark skin tone"]={ 0x1F90F, 0x1F3FE },
+ ["pinching hand: medium-light skin tone"]={ 0x1F90F, 0x1F3FC },
["pine decoration"]={ 0x1F38D },
["pineapple"]={ 0x1F34D },
["ping pong"]={ 0x1F3D3 },
+ ["pirate flag"]={ 0x1F3F4, 0x200D, 0x2620, 0xFE0F },
["pisces"]={ 0x2653 },
["pistol"]={ 0x1F52B },
- ["pitcairn islands"]={ 0x1F1F5, 0x1F1F3 },
["pizza"]={ 0x1F355 },
["place of worship"]={ 0x1F6D0 },
- ["play button"]={ 0x25B6 },
- ["play or pause button"]={ 0x23EF },
- ["poland"]={ 0x1F1F5, 0x1F1F1 },
+ ["play button"]={ 0x25B6, 0xFE0F },
+ ["play or pause button"]={ 0x23EF, 0xFE0F },
+ ["pleading face"]={ 0x1F97A },
+ ["plus sign"]={ 0x2795 },
["police car"]={ 0x1F693 },
["police car light"]={ 0x1F6A8 },
["police officer"]={ 0x1F46E },
@@ -1757,7 +2070,6 @@ return {
["poodle"]={ 0x1F429 },
["pool 8 ball"]={ 0x1F3B1 },
["popcorn"]={ 0x1F37F },
- ["portugal"]={ 0x1F1F5, 0x1F1F9 },
["post office"]={ 0x1F3E4 },
["postal horn"]={ 0x1F4EF },
["postbox"]={ 0x1F4EE },
@@ -1766,7 +2078,7 @@ return {
["potato"]={ 0x1F954 },
["poultry leg"]={ 0x1F357 },
["pound banknote"]={ 0x1F4B7 },
- ["pouting cat face"]={ 0x1F63E },
+ ["pouting cat"]={ 0x1F63E },
["pouting face"]={ 0x1F621 },
["prayer beads"]={ 0x1F4FF },
["pregnant woman"]={ 0x1F930 },
@@ -1788,24 +2100,27 @@ return {
["princess: medium skin tone"]={ 0x1F478, 0x1F3FD },
["princess: medium-dark skin tone"]={ 0x1F478, 0x1F3FE },
["princess: medium-light skin tone"]={ 0x1F478, 0x1F3FC },
- ["printer"]={ 0x1F5A8 },
+ ["printer"]={ 0x1F5A8, 0xFE0F },
+ ["probing cane"]={ 0x1F9AF },
["prohibited"]={ 0x1F6AB },
- ["puerto rico"]={ 0x1F1F5, 0x1F1F7 },
+ ["purple circle"]={ 0x1F7E3 },
["purple heart"]={ 0x1F49C },
+ ["purple square"]={ 0x1F7EA },
["purse"]={ 0x1F45B },
["pushpin"]={ 0x1F4CC },
- ["qatar"]={ 0x1F1F6, 0x1F1E6 },
+ ["puzzle piece"]={ 0x1F9E9 },
["question mark"]={ 0x2753 },
["rabbit"]={ 0x1F407 },
["rabbit face"]={ 0x1F430 },
- ["racing car"]={ 0x1F3CE },
+ ["raccoon"]={ 0x1F99D },
+ ["racing car"]={ 0x1F3CE, 0xFE0F },
["radio"]={ 0x1F4FB },
["radio button"]={ 0x1F518 },
- ["radioactive"]={ 0x2622 },
+ ["radioactive"]={ 0x2622, 0xFE0F },
["railway car"]={ 0x1F683 },
- ["railway track"]={ 0x1F6E4 },
+ ["railway track"]={ 0x1F6E4, 0xFE0F },
["rainbow"]={ 0x1F308 },
- ["rainbow flag"]={ 0x1F3F3, 0x200D, 0x1F308 },
+ ["rainbow flag"]={ 0x1F3F3, 0xFE0F, 0x200D, 0x1F308 },
["raised back of hand"]={ 0x1F91A },
["raised back of hand: dark skin tone"]={ 0x1F91A, 0x1F3FF },
["raised back of hand: light skin tone"]={ 0x1F91A, 0x1F3FB },
@@ -1819,12 +2134,6 @@ return {
["raised fist: medium-dark skin tone"]={ 0x270A, 0x1F3FE },
["raised fist: medium-light skin tone"]={ 0x270A, 0x1F3FC },
["raised hand"]={ 0x270B },
- ["raised hand with fingers splayed"]={ 0x1F590 },
- ["raised hand with fingers splayed: dark skin tone"]={ 0x1F590, 0x1F3FF },
- ["raised hand with fingers splayed: light skin tone"]={ 0x1F590, 0x1F3FB },
- ["raised hand with fingers splayed: medium skin tone"]={ 0x1F590, 0x1F3FD },
- ["raised hand with fingers splayed: medium-dark skin tone"]={ 0x1F590, 0x1F3FE },
- ["raised hand with fingers splayed: medium-light skin tone"]={ 0x1F590, 0x1F3FC },
["raised hand: dark skin tone"]={ 0x270B, 0x1F3FF },
["raised hand: light skin tone"]={ 0x270B, 0x1F3FB },
["raised hand: medium skin tone"]={ 0x270B, 0x1F3FD },
@@ -1838,62 +2147,65 @@ return {
["raising hands: medium-light skin tone"]={ 0x1F64C, 0x1F3FC },
["ram"]={ 0x1F40F },
["rat"]={ 0x1F400 },
- ["record button"]={ 0x23FA },
- ["recycling symbol"]={ 0x267B },
+ ["razor"]={ 0x1FA92 },
+ ["receipt"]={ 0x1F9FE },
+ ["record button"]={ 0x23FA, 0xFE0F },
+ ["recycling symbol"]={ 0x267B, 0xFE0F },
["red apple"]={ 0x1F34E },
["red circle"]={ 0x1F534 },
- ["red heart"]={ 0x2764 },
+ ["red envelope"]={ 0x1F9E7 },
+ ["red heart"]={ 0x2764, 0xFE0F },
["red paper lantern"]={ 0x1F3EE },
+ ["red square"]={ 0x1F7E5 },
["red triangle pointed down"]={ 0x1F53B },
["red triangle pointed up"]={ 0x1F53A },
- ["registered"]={ 0xAE },
+ ["registered"]={ 0xAE, 0xFE0F },
["relieved face"]={ 0x1F60C },
- ["reminder ribbon"]={ 0x1F397 },
+ ["reminder ribbon"]={ 0x1F397, 0xFE0F },
["repeat button"]={ 0x1F501 },
["repeat single button"]={ 0x1F502 },
- ["rescue worker’s helmet"]={ 0x26D1 },
+ ["rescue worker’s helmet"]={ 0x26D1, 0xFE0F },
["restroom"]={ 0x1F6BB },
- ["reverse button"]={ 0x25C0 },
+ ["reverse button"]={ 0x25C0, 0xFE0F },
["revolving hearts"]={ 0x1F49E },
["rhinoceros"]={ 0x1F98F },
["ribbon"]={ 0x1F380 },
["rice ball"]={ 0x1F359 },
["rice cracker"]={ 0x1F358 },
- ["right anger bubble"]={ 0x1F5EF },
- ["right arrow"]={ 0x27A1 },
- ["right arrow curving down"]={ 0x2935 },
- ["right arrow curving left"]={ 0x21A9 },
- ["right arrow curving up"]={ 0x2934 },
+ ["right anger bubble"]={ 0x1F5EF, 0xFE0F },
+ ["right arrow"]={ 0x27A1, 0xFE0F },
+ ["right arrow curving down"]={ 0x2935, 0xFE0F },
+ ["right arrow curving left"]={ 0x21A9, 0xFE0F },
+ ["right arrow curving up"]={ 0x2934, 0xFE0F },
["right-facing fist"]={ 0x1F91C },
["right-facing fist: dark skin tone"]={ 0x1F91C, 0x1F3FF },
["right-facing fist: light skin tone"]={ 0x1F91C, 0x1F3FB },
["right-facing fist: medium skin tone"]={ 0x1F91C, 0x1F3FD },
["right-facing fist: medium-dark skin tone"]={ 0x1F91C, 0x1F3FE },
["right-facing fist: medium-light skin tone"]={ 0x1F91C, 0x1F3FC },
- ["right-pointing magnifying glass"]={ 0x1F50E },
["ring"]={ 0x1F48D },
+ ["ringed planet"]={ 0x1FA90 },
["roasted sweet potato"]={ 0x1F360 },
- ["robot face"]={ 0x1F916 },
+ ["robot"]={ 0x1F916 },
["rocket"]={ 0x1F680 },
- ["rolled-up newspaper"]={ 0x1F5DE },
+ ["roll of paper"]={ 0x1F9FB },
+ ["rolled-up newspaper"]={ 0x1F5DE, 0xFE0F },
["roller coaster"]={ 0x1F3A2 },
["rolling on the floor laughing"]={ 0x1F923 },
- ["romania"]={ 0x1F1F7, 0x1F1F4 },
["rooster"]={ 0x1F413 },
["rose"]={ 0x1F339 },
- ["rosette"]={ 0x1F3F5 },
+ ["rosette"]={ 0x1F3F5, 0xFE0F },
["round pushpin"]={ 0x1F4CD },
["rugby football"]={ 0x1F3C9 },
["running shirt"]={ 0x1F3BD },
["running shoe"]={ 0x1F45F },
- ["russia"]={ 0x1F1F7, 0x1F1FA },
- ["rwanda"]={ 0x1F1F7, 0x1F1FC },
- ["réunion"]={ 0x1F1F7, 0x1F1EA },
+ ["sad but relieved face"]={ 0x1F625 },
+ ["safety pin"]={ 0x1F9F7 },
+ ["safety vest"]={ 0x1F9BA },
["sagittarius"]={ 0x2650 },
["sailboat"]={ 0x26F5 },
["sake"]={ 0x1F376 },
- ["samoa"]={ 0x1F1FC, 0x1F1F8 },
- ["san marino"]={ 0x1F1F8, 0x1F1F2 },
+ ["salt"]={ 0x1F9C2 },
["sandwich"]={ 0x1F96A },
["santa claus"]={ 0x1F385 },
["santa claus: dark skin tone"]={ 0x1F385, 0x1F3FF },
@@ -1901,18 +2213,16 @@ return {
["santa claus: medium skin tone"]={ 0x1F385, 0x1F3FD },
["santa claus: medium-dark skin tone"]={ 0x1F385, 0x1F3FE },
["santa claus: medium-light skin tone"]={ 0x1F385, 0x1F3FC },
- ["satellite"]={ 0x1F6F0 },
+ ["sari"]={ 0x1F97B },
+ ["satellite"]={ 0x1F6F0, 0xFE0F },
["satellite antenna"]={ 0x1F4E1 },
- ["saudi arabia"]={ 0x1F1F8, 0x1F1E6 },
["sauropod"]={ 0x1F995 },
["saxophone"]={ 0x1F3B7 },
["scarf"]={ 0x1F9E3 },
["school"]={ 0x1F3EB },
- ["school backpack"]={ 0x1F392 },
- ["scissors"]={ 0x2702 },
+ ["scissors"]={ 0x2702, 0xFE0F },
+ ["scorpio"]={ 0x264F },
["scorpion"]={ 0x1F982 },
- ["scorpius"]={ 0x264F },
- ["scotland"]={ 0x1F3F4, 0xE0067, 0xE0062, 0xE0073, 0xE0063, 0xE0074, 0xE007F },
["scroll"]={ 0x1F4DC },
["seat"]={ 0x1F4BA },
["see-no-evil monkey"]={ 0x1F648 },
@@ -1923,94 +2233,82 @@ return {
["selfie: medium skin tone"]={ 0x1F933, 0x1F3FD },
["selfie: medium-dark skin tone"]={ 0x1F933, 0x1F3FE },
["selfie: medium-light skin tone"]={ 0x1F933, 0x1F3FC },
- ["senegal"]={ 0x1F1F8, 0x1F1F3 },
- ["serbia"]={ 0x1F1F7, 0x1F1F8 },
+ ["service dog"]={ 0x1F415, 0x200D, 0x1F9BA },
["seven o’clock"]={ 0x1F556 },
["seven-thirty"]={ 0x1F562 },
- ["seychelles"]={ 0x1F1F8, 0x1F1E8 },
["shallow pan of food"]={ 0x1F958 },
- ["shamrock"]={ 0x2618 },
+ ["shamrock"]={ 0x2618, 0xFE0F },
["shark"]={ 0x1F988 },
["shaved ice"]={ 0x1F367 },
["sheaf of rice"]={ 0x1F33E },
- ["shield"]={ 0x1F6E1 },
- ["shinto shrine"]={ 0x26E9 },
+ ["shield"]={ 0x1F6E1, 0xFE0F },
+ ["shinto shrine"]={ 0x26E9, 0xFE0F },
["ship"]={ 0x1F6A2 },
["shooting star"]={ 0x1F320 },
- ["shopping bags"]={ 0x1F6CD },
+ ["shopping bags"]={ 0x1F6CD, 0xFE0F },
["shopping cart"]={ 0x1F6D2 },
["shortcake"]={ 0x1F370 },
+ ["shorts"]={ 0x1FA73 },
["shower"]={ 0x1F6BF },
["shrimp"]={ 0x1F990 },
["shuffle tracks button"]={ 0x1F500 },
["shushing face"]={ 0x1F92B },
- ["sierra leone"]={ 0x1F1F8, 0x1F1F1 },
["sign of the horns"]={ 0x1F918 },
["sign of the horns: dark skin tone"]={ 0x1F918, 0x1F3FF },
["sign of the horns: light skin tone"]={ 0x1F918, 0x1F3FB },
["sign of the horns: medium skin tone"]={ 0x1F918, 0x1F3FD },
["sign of the horns: medium-dark skin tone"]={ 0x1F918, 0x1F3FE },
["sign of the horns: medium-light skin tone"]={ 0x1F918, 0x1F3FC },
- ["singapore"]={ 0x1F1F8, 0x1F1EC },
- ["sint maarten"]={ 0x1F1F8, 0x1F1FD },
["six o’clock"]={ 0x1F555 },
["six-thirty"]={ 0x1F561 },
- ["skier"]={ 0x26F7 },
+ ["skateboard"]={ 0x1F6F9 },
+ ["skier"]={ 0x26F7, 0xFE0F },
["skis"]={ 0x1F3BF },
["skull"]={ 0x1F480 },
- ["skull and crossbones"]={ 0x2620 },
+ ["skull and crossbones"]={ 0x2620, 0xFE0F },
+ ["skunk"]={ 0x1F9A8 },
["sled"]={ 0x1F6F7 },
["sleeping face"]={ 0x1F634 },
["sleepy face"]={ 0x1F62A },
["slightly frowning face"]={ 0x1F641 },
["slightly smiling face"]={ 0x1F642 },
["slot machine"]={ 0x1F3B0 },
- ["slovakia"]={ 0x1F1F8, 0x1F1F0 },
- ["slovenia"]={ 0x1F1F8, 0x1F1EE },
- ["small airplane"]={ 0x1F6E9 },
+ ["sloth"]={ 0x1F9A5 },
+ ["small airplane"]={ 0x1F6E9, 0xFE0F },
["small blue diamond"]={ 0x1F539 },
["small orange diamond"]={ 0x1F538 },
- ["smiling cat face with heart-eyes"]={ 0x1F63B },
- ["smiling cat face with open mouth"]={ 0x1F63A },
- ["smiling face"]={ 0x263A },
+ ["smiling cat with heart-eyes"]={ 0x1F63B },
+ ["smiling face"]={ 0x263A, 0xFE0F },
["smiling face with halo"]={ 0x1F607 },
["smiling face with heart-eyes"]={ 0x1F60D },
+ ["smiling face with hearts"]={ 0x1F970 },
["smiling face with horns"]={ 0x1F608 },
- ["smiling face with open mouth"]={ 0x1F603 },
- ["smiling face with open mouth & closed eyes"]={ 0x1F606 },
- ["smiling face with open mouth & cold sweat"]={ 0x1F605 },
- ["smiling face with open mouth & smiling eyes"]={ 0x1F604 },
["smiling face with smiling eyes"]={ 0x1F60A },
["smiling face with sunglasses"]={ 0x1F60E },
["smirking face"]={ 0x1F60F },
["snail"]={ 0x1F40C },
["snake"]={ 0x1F40D },
["sneezing face"]={ 0x1F927 },
- ["snow-capped mountain"]={ 0x1F3D4 },
+ ["snow-capped mountain"]={ 0x1F3D4, 0xFE0F },
["snowboarder"]={ 0x1F3C2 },
["snowboarder: dark skin tone"]={ 0x1F3C2, 0x1F3FF },
["snowboarder: light skin tone"]={ 0x1F3C2, 0x1F3FB },
["snowboarder: medium skin tone"]={ 0x1F3C2, 0x1F3FD },
["snowboarder: medium-dark skin tone"]={ 0x1F3C2, 0x1F3FE },
["snowboarder: medium-light skin tone"]={ 0x1F3C2, 0x1F3FC },
- ["snowflake"]={ 0x2744 },
- ["snowman"]={ 0x2603 },
+ ["snowflake"]={ 0x2744, 0xFE0F },
+ ["snowman"]={ 0x2603, 0xFE0F },
["snowman without snow"]={ 0x26C4 },
+ ["soap"]={ 0x1F9FC },
["soccer ball"]={ 0x26BD },
["socks"]={ 0x1F9E6 },
["soft ice cream"]={ 0x1F366 },
- ["solomon islands"]={ 0x1F1F8, 0x1F1E7 },
- ["somalia"]={ 0x1F1F8, 0x1F1F4 },
+ ["softball"]={ 0x1F94E },
["soon arrow"]={ 0x1F51C },
["sos button"]={ 0x1F198 },
- ["south africa"]={ 0x1F1FF, 0x1F1E6 },
- ["south georgia & south sandwich islands"]={ 0x1F1EC, 0x1F1F8 },
- ["south korea"]={ 0x1F1F0, 0x1F1F7 },
- ["south sudan"]={ 0x1F1F8, 0x1F1F8 },
- ["spade suit"]={ 0x2660 },
+ ["spade suit"]={ 0x2660, 0xFE0F },
["spaghetti"]={ 0x1F35D },
- ["spain"]={ 0x1F1EA, 0x1F1F8 },
- ["sparkle"]={ 0x2747 },
+ ["sparkle"]={ 0x2747, 0xFE0F },
["sparkler"]={ 0x1F387 },
["sparkles"]={ 0x2728 },
["sparkling heart"]={ 0x1F496 },
@@ -2018,79 +2316,79 @@ return {
["speaker high volume"]={ 0x1F50A },
["speaker low volume"]={ 0x1F508 },
["speaker medium volume"]={ 0x1F509 },
- ["speaking head"]={ 0x1F5E3 },
+ ["speaking head"]={ 0x1F5E3, 0xFE0F },
["speech balloon"]={ 0x1F4AC },
["speedboat"]={ 0x1F6A4 },
- ["spider"]={ 0x1F577 },
- ["spider web"]={ 0x1F578 },
- ["spiral calendar"]={ 0x1F5D3 },
- ["spiral notepad"]={ 0x1F5D2 },
+ ["spider"]={ 0x1F577, 0xFE0F },
+ ["spider web"]={ 0x1F578, 0xFE0F },
+ ["spiral calendar"]={ 0x1F5D3, 0xFE0F },
+ ["spiral notepad"]={ 0x1F5D2, 0xFE0F },
["spiral shell"]={ 0x1F41A },
+ ["sponge"]={ 0x1F9FD },
["spoon"]={ 0x1F944 },
["sport utility vehicle"]={ 0x1F699 },
["sports medal"]={ 0x1F3C5 },
["spouting whale"]={ 0x1F433 },
["squid"]={ 0x1F991 },
- ["sri lanka"]={ 0x1F1F1, 0x1F1F0 },
- ["st. barthélemy"]={ 0x1F1E7, 0x1F1F1 },
- ["st. helena"]={ 0x1F1F8, 0x1F1ED },
- ["st. kitts & nevis"]={ 0x1F1F0, 0x1F1F3 },
- ["st. lucia"]={ 0x1F1F1, 0x1F1E8 },
- ["st. martin"]={ 0x1F1F2, 0x1F1EB },
- ["st. pierre & miquelon"]={ 0x1F1F5, 0x1F1F2 },
- ["st. vincent & grenadines"]={ 0x1F1FB, 0x1F1E8 },
- ["stadium"]={ 0x1F3DF },
- ["star and crescent"]={ 0x262A },
- ["star of david"]={ 0x2721 },
+ ["squinting face with tongue"]={ 0x1F61D },
+ ["stadium"]={ 0x1F3DF, 0xFE0F },
+ ["star"]={ 0x2B50 },
+ ["star and crescent"]={ 0x262A, 0xFE0F },
+ ["star of david"]={ 0x2721, 0xFE0F },
["star-struck"]={ 0x1F929 },
["station"]={ 0x1F689 },
["statue of liberty"]={ 0x1F5FD },
["steaming bowl"]={ 0x1F35C },
- ["stop button"]={ 0x23F9 },
+ ["stethoscope"]={ 0x1FA7A },
+ ["stop button"]={ 0x23F9, 0xFE0F },
["stop sign"]={ 0x1F6D1 },
- ["stopwatch"]={ 0x23F1 },
+ ["stopwatch"]={ 0x23F1, 0xFE0F },
["straight ruler"]={ 0x1F4CF },
["strawberry"]={ 0x1F353 },
- ["studio microphone"]={ 0x1F399 },
+ ["studio microphone"]={ 0x1F399, 0xFE0F },
["stuffed flatbread"]={ 0x1F959 },
- ["sudan"]={ 0x1F1F8, 0x1F1E9 },
- ["sun"]={ 0x2600 },
+ ["sun"]={ 0x2600, 0xFE0F },
["sun behind cloud"]={ 0x26C5 },
- ["sun behind large cloud"]={ 0x1F325 },
- ["sun behind rain cloud"]={ 0x1F326 },
- ["sun behind small cloud"]={ 0x1F324 },
+ ["sun behind large cloud"]={ 0x1F325, 0xFE0F },
+ ["sun behind rain cloud"]={ 0x1F326, 0xFE0F },
+ ["sun behind small cloud"]={ 0x1F324, 0xFE0F },
["sun with face"]={ 0x1F31E },
["sunflower"]={ 0x1F33B },
- ["sunglasses"]={ 0x1F576 },
+ ["sunglasses"]={ 0x1F576, 0xFE0F },
["sunrise"]={ 0x1F305 },
["sunrise over mountains"]={ 0x1F304 },
["sunset"]={ 0x1F307 },
- ["suriname"]={ 0x1F1F8, 0x1F1F7 },
+ ["superhero"]={ 0x1F9B8 },
+ ["superhero: dark skin tone"]={ 0x1F9B8, 0x1F3FF },
+ ["superhero: light skin tone"]={ 0x1F9B8, 0x1F3FB },
+ ["superhero: medium skin tone"]={ 0x1F9B8, 0x1F3FD },
+ ["superhero: medium-dark skin tone"]={ 0x1F9B8, 0x1F3FE },
+ ["superhero: medium-light skin tone"]={ 0x1F9B8, 0x1F3FC },
+ ["supervillain"]={ 0x1F9B9 },
+ ["supervillain: dark skin tone"]={ 0x1F9B9, 0x1F3FF },
+ ["supervillain: light skin tone"]={ 0x1F9B9, 0x1F3FB },
+ ["supervillain: medium skin tone"]={ 0x1F9B9, 0x1F3FD },
+ ["supervillain: medium-dark skin tone"]={ 0x1F9B9, 0x1F3FE },
+ ["supervillain: medium-light skin tone"]={ 0x1F9B9, 0x1F3FC },
["sushi"]={ 0x1F363 },
["suspension railway"]={ 0x1F69F },
- ["svalbard & jan mayen"]={ 0x1F1F8, 0x1F1EF },
- ["swaziland"]={ 0x1F1F8, 0x1F1FF },
+ ["swan"]={ 0x1F9A2 },
["sweat droplets"]={ 0x1F4A6 },
- ["sweden"]={ 0x1F1F8, 0x1F1EA },
- ["switzerland"]={ 0x1F1E8, 0x1F1ED },
+ ["swim brief"]={ 0x1FA72 },
["synagogue"]={ 0x1F54D },
- ["syria"]={ 0x1F1F8, 0x1F1FE },
["syringe"]={ 0x1F489 },
- ["são tomé & príncipe"]={ 0x1F1F8, 0x1F1F9 },
["t-rex"]={ 0x1F996 },
["t-shirt"]={ 0x1F455 },
["taco"]={ 0x1F32E },
- ["taiwan"]={ 0x1F1F9, 0x1F1FC },
- ["tajikistan"]={ 0x1F1F9, 0x1F1EF },
["takeout box"]={ 0x1F961 },
["tanabata tree"]={ 0x1F38B },
["tangerine"]={ 0x1F34A },
- ["tanzania"]={ 0x1F1F9, 0x1F1FF },
["taurus"]={ 0x2649 },
["taxi"]={ 0x1F695 },
["teacup without handle"]={ 0x1F375 },
["tear-off calendar"]={ 0x1F4C6 },
- ["telephone"]={ 0x260E },
+ ["teddy bear"]={ 0x1F9F8 },
+ ["telephone"]={ 0x260E, 0xFE0F },
["telephone receiver"]={ 0x1F4DE },
["telescope"]={ 0x1F52D },
["television"]={ 0x1F4FA },
@@ -2098,10 +2396,11 @@ return {
["ten-thirty"]={ 0x1F565 },
["tennis"]={ 0x1F3BE },
["tent"]={ 0x26FA },
- ["thailand"]={ 0x1F1F9, 0x1F1ED },
- ["thermometer"]={ 0x1F321 },
+ ["test tube"]={ 0x1F9EA },
+ ["thermometer"]={ 0x1F321, 0xFE0F },
["thinking face"]={ 0x1F914 },
["thought balloon"]={ 0x1F4AD },
+ ["thread"]={ 0x1F9F5 },
["three o’clock"]={ 0x1F552 },
["three-thirty"]={ 0x1F55E },
["thumbs down"]={ 0x1F44E },
@@ -2119,30 +2418,26 @@ return {
["ticket"]={ 0x1F3AB },
["tiger"]={ 0x1F405 },
["tiger face"]={ 0x1F42F },
- ["timer clock"]={ 0x23F2 },
- ["timor-leste"]={ 0x1F1F9, 0x1F1F1 },
+ ["timer clock"]={ 0x23F2, 0xFE0F },
["tired face"]={ 0x1F62B },
- ["togo"]={ 0x1F1F9, 0x1F1EC },
["toilet"]={ 0x1F6BD },
- ["tokelau"]={ 0x1F1F9, 0x1F1F0 },
["tokyo tower"]={ 0x1F5FC },
["tomato"]={ 0x1F345 },
- ["tonga"]={ 0x1F1F9, 0x1F1F4 },
["tongue"]={ 0x1F445 },
+ ["toolbox"]={ 0x1F9F0 },
+ ["tooth"]={ 0x1F9B7 },
["top arrow"]={ 0x1F51D },
["top hat"]={ 0x1F3A9 },
- ["tornado"]={ 0x1F32A },
- ["trackball"]={ 0x1F5B2 },
+ ["tornado"]={ 0x1F32A, 0xFE0F },
+ ["trackball"]={ 0x1F5B2, 0xFE0F },
["tractor"]={ 0x1F69C },
- ["trade mark"]={ 0x2122 },
+ ["trade mark"]={ 0x2122, 0xFE0F },
["train"]={ 0x1F686 },
["tram"]={ 0x1F68A },
["tram car"]={ 0x1F68B },
["triangular flag"]={ 0x1F6A9 },
["triangular ruler"]={ 0x1F4D0 },
["trident emblem"]={ 0x1F531 },
- ["trinidad & tobago"]={ 0x1F1F9, 0x1F1F9 },
- ["tristan da cunha"]={ 0x1F1F9, 0x1F1E6 },
["trolleybus"]={ 0x1F68E },
["trophy"]={ 0x1F3C6 },
["tropical drink"]={ 0x1F379 },
@@ -2150,55 +2445,36 @@ return {
["trumpet"]={ 0x1F3BA },
["tulip"]={ 0x1F337 },
["tumbler glass"]={ 0x1F943 },
- ["tunisia"]={ 0x1F1F9, 0x1F1F3 },
- ["turkey"]={ 0x1F1F9, 0x1F1F7 },
- ["turkmenistan"]={ 0x1F1F9, 0x1F1F2 },
- ["turks & caicos islands"]={ 0x1F1F9, 0x1F1E8 },
+ ["turkey"]={ 0x1F983 },
["turtle"]={ 0x1F422 },
- ["tuvalu"]={ 0x1F1F9, 0x1F1FB },
["twelve o’clock"]={ 0x1F55B },
["twelve-thirty"]={ 0x1F567 },
["two hearts"]={ 0x1F495 },
- ["two men holding hands"]={ 0x1F46C },
["two o’clock"]={ 0x1F551 },
- ["two women holding hands"]={ 0x1F46D },
["two-hump camel"]={ 0x1F42B },
["two-thirty"]={ 0x1F55D },
- ["u.s. outlying islands"]={ 0x1F1FA, 0x1F1F2 },
- ["u.s. virgin islands"]={ 0x1F1FB, 0x1F1EE },
- ["uganda"]={ 0x1F1FA, 0x1F1EC },
- ["ukraine"]={ 0x1F1FA, 0x1F1E6 },
- ["umbrella"]={ 0x2602 },
- ["umbrella on ground"]={ 0x26F1 },
+ ["umbrella"]={ 0x2602, 0xFE0F },
+ ["umbrella on ground"]={ 0x26F1, 0xFE0F },
["umbrella with rain drops"]={ 0x2614 },
["unamused face"]={ 0x1F612 },
- ["unicorn face"]={ 0x1F984 },
- ["united arab emirates"]={ 0x1F1E6, 0x1F1EA },
- ["united kingdom"]={ 0x1F1EC, 0x1F1E7 },
- ["united nations"]={ 0x1F1FA, 0x1F1F3 },
- ["united states"]={ 0x1F1FA, 0x1F1F8 },
+ ["unicorn"]={ 0x1F984 },
["unlocked"]={ 0x1F513 },
- ["up arrow"]={ 0x2B06 },
- ["up button"]={ 0x1F53C },
+ ["up arrow"]={ 0x2B06, 0xFE0F },
["up! button"]={ 0x1F199 },
- ["up-down arrow"]={ 0x2195 },
- ["up-left arrow"]={ 0x2196 },
- ["up-right arrow"]={ 0x2197 },
+ ["up-down arrow"]={ 0x2195, 0xFE0F },
+ ["up-left arrow"]={ 0x2196, 0xFE0F },
+ ["up-right arrow"]={ 0x2197, 0xFE0F },
["upside-down face"]={ 0x1F643 },
- ["uruguay"]={ 0x1F1FA, 0x1F1FE },
- ["uzbekistan"]={ 0x1F1FA, 0x1F1FF },
+ ["upwards button"]={ 0x1F53C },
["vampire"]={ 0x1F9DB },
["vampire: dark skin tone"]={ 0x1F9DB, 0x1F3FF },
["vampire: light skin tone"]={ 0x1F9DB, 0x1F3FB },
["vampire: medium skin tone"]={ 0x1F9DB, 0x1F3FD },
["vampire: medium-dark skin tone"]={ 0x1F9DB, 0x1F3FE },
["vampire: medium-light skin tone"]={ 0x1F9DB, 0x1F3FC },
- ["vanuatu"]={ 0x1F1FB, 0x1F1FA },
- ["vatican city"]={ 0x1F1FB, 0x1F1E6 },
- ["venezuela"]={ 0x1F1FB, 0x1F1EA },
["vertical traffic light"]={ 0x1F6A6 },
["vibration mode"]={ 0x1F4F3 },
- ["victory hand"]={ 0x270C },
+ ["victory hand"]={ 0x270C, 0xFE0F },
["victory hand: dark skin tone"]={ 0x270C, 0x1F3FF },
["victory hand: light skin tone"]={ 0x270C, 0x1F3FB },
["victory hand: medium skin tone"]={ 0x270C, 0x1F3FD },
@@ -2207,7 +2483,6 @@ return {
["video camera"]={ 0x1F4F9 },
["video game"]={ 0x1F3AE },
["videocassette"]={ 0x1F4FC },
- ["vietnam"]={ 0x1F1FB, 0x1F1F3 },
["violin"]={ 0x1F3BB },
["virgo"]={ 0x264D },
["volcano"]={ 0x1F30B },
@@ -2219,12 +2494,11 @@ return {
["vulcan salute: medium skin tone"]={ 0x1F596, 0x1F3FD },
["vulcan salute: medium-dark skin tone"]={ 0x1F596, 0x1F3FE },
["vulcan salute: medium-light skin tone"]={ 0x1F596, 0x1F3FC },
- ["wales"]={ 0x1F3F4, 0xE0067, 0xE0062, 0xE0077, 0xE006C, 0xE0073, 0xE007F },
- ["wallis & futuna"]={ 0x1F1FC, 0x1F1EB },
+ ["waffle"]={ 0x1F9C7 },
["waning crescent moon"]={ 0x1F318 },
["waning gibbous moon"]={ 0x1F316 },
- ["warning"]={ 0x26A0 },
- ["wastebasket"]={ 0x1F5D1 },
+ ["warning"]={ 0x26A0, 0xFE0F },
+ ["wastebasket"]={ 0x1F5D1, 0xFE0F },
["watch"]={ 0x231A },
["water buffalo"]={ 0x1F403 },
["water closet"]={ 0x1F6BE },
@@ -2236,35 +2510,60 @@ return {
["waving hand: medium skin tone"]={ 0x1F44B, 0x1F3FD },
["waving hand: medium-dark skin tone"]={ 0x1F44B, 0x1F3FE },
["waving hand: medium-light skin tone"]={ 0x1F44B, 0x1F3FC },
- ["wavy dash"]={ 0x3030 },
+ ["wavy dash"]={ 0x3030, 0xFE0F },
["waxing crescent moon"]={ 0x1F312 },
["waxing gibbous moon"]={ 0x1F314 },
- ["weary cat face"]={ 0x1F640 },
+ ["weary cat"]={ 0x1F640 },
["weary face"]={ 0x1F629 },
["wedding"]={ 0x1F492 },
- ["western sahara"]={ 0x1F1EA, 0x1F1ED },
["whale"]={ 0x1F40B },
- ["wheel of dharma"]={ 0x2638 },
+ ["wheel of dharma"]={ 0x2638, 0xFE0F },
["wheelchair symbol"]={ 0x267F },
["white circle"]={ 0x26AA },
["white exclamation mark"]={ 0x2755 },
- ["white flag"]={ 0x1F3F3 },
+ ["white flag"]={ 0x1F3F3, 0xFE0F },
["white flower"]={ 0x1F4AE },
- ["white heavy check mark"]={ 0x2705 },
+ ["white heart"]={ 0x1F90D },
["white large square"]={ 0x2B1C },
- ["white medium square"]={ 0x25FB },
- ["white medium star"]={ 0x2B50 },
+ ["white medium square"]={ 0x25FB, 0xFE0F },
["white medium-small square"]={ 0x25FD },
["white question mark"]={ 0x2754 },
- ["white small square"]={ 0x25AB },
+ ["white small square"]={ 0x25AB, 0xFE0F },
["white square button"]={ 0x1F533 },
["wilted flower"]={ 0x1F940 },
["wind chime"]={ 0x1F390 },
- ["wind face"]={ 0x1F32C },
+ ["wind face"]={ 0x1F32C, 0xFE0F },
["wine glass"]={ 0x1F377 },
["winking face"]={ 0x1F609 },
- ["wolf face"]={ 0x1F43A },
+ ["winking face with tongue"]={ 0x1F61C },
+ ["wolf"]={ 0x1F43A },
["woman"]={ 0x1F469 },
+ ["woman and man holding hands"]={ 0x1F46B },
+ ["woman and man holding hands: dark skin tone"]={ 0x1F46B, 0x1F3FF },
+ ["woman and man holding hands: dark skin tone, light skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB },
+ ["woman and man holding hands: dark skin tone, medium skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD },
+ ["woman and man holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE },
+ ["woman and man holding hands: dark skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC },
+ ["woman and man holding hands: light skin tone"]={ 0x1F46B, 0x1F3FB },
+ ["woman and man holding hands: light skin tone, dark skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF },
+ ["woman and man holding hands: light skin tone, medium skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD },
+ ["woman and man holding hands: light skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE },
+ ["woman and man holding hands: light skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC },
+ ["woman and man holding hands: medium skin tone"]={ 0x1F46B, 0x1F3FD },
+ ["woman and man holding hands: medium skin tone, dark skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF },
+ ["woman and man holding hands: medium skin tone, light skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB },
+ ["woman and man holding hands: medium skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE },
+ ["woman and man holding hands: medium skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC },
+ ["woman and man holding hands: medium-dark skin tone"]={ 0x1F46B, 0x1F3FE },
+ ["woman and man holding hands: medium-dark skin tone, dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF },
+ ["woman and man holding hands: medium-dark skin tone, light skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB },
+ ["woman and man holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD },
+ ["woman and man holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FC },
+ ["woman and man holding hands: medium-light skin tone"]={ 0x1F46B, 0x1F3FC },
+ ["woman and man holding hands: medium-light skin tone, dark skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FF },
+ ["woman and man holding hands: medium-light skin tone, light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FB },
+ ["woman and man holding hands: medium-light skin tone, medium skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FD },
+ ["woman and man holding hands: medium-light skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F468, 0x1F3FE },
["woman artist"]={ 0x1F469, 0x200D, 0x1F3A8 },
["woman artist: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F3A8 },
["woman artist: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F3A8 },
@@ -2277,42 +2576,42 @@ return {
["woman astronaut: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F680 },
["woman astronaut: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F680 },
["woman astronaut: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F680 },
- ["woman biking"]={ 0x1F6B4, 0x200D, 0x2640 },
- ["woman biking: dark skin tone"]={ 0x1F6B4, 0x1F3FF, 0x200D, 0x2640 },
- ["woman biking: light skin tone"]={ 0x1F6B4, 0x1F3FB, 0x200D, 0x2640 },
- ["woman biking: medium skin tone"]={ 0x1F6B4, 0x1F3FD, 0x200D, 0x2640 },
- ["woman biking: medium-dark skin tone"]={ 0x1F6B4, 0x1F3FE, 0x200D, 0x2640 },
- ["woman biking: medium-light skin tone"]={ 0x1F6B4, 0x1F3FC, 0x200D, 0x2640 },
- ["woman bouncing ball"]={ 0x26F9, 0x200D, 0x2640 },
- ["woman bouncing ball: dark skin tone"]={ 0x26F9, 0x1F3FF, 0x200D, 0x2640 },
- ["woman bouncing ball: light skin tone"]={ 0x26F9, 0x1F3FB, 0x200D, 0x2640 },
- ["woman bouncing ball: medium skin tone"]={ 0x26F9, 0x1F3FD, 0x200D, 0x2640 },
- ["woman bouncing ball: medium-dark skin tone"]={ 0x26F9, 0x1F3FE, 0x200D, 0x2640 },
- ["woman bouncing ball: medium-light skin tone"]={ 0x26F9, 0x1F3FC, 0x200D, 0x2640 },
- ["woman bowing"]={ 0x1F647, 0x200D, 0x2640 },
- ["woman bowing: dark skin tone"]={ 0x1F647, 0x1F3FF, 0x200D, 0x2640 },
- ["woman bowing: light skin tone"]={ 0x1F647, 0x1F3FB, 0x200D, 0x2640 },
- ["woman bowing: medium skin tone"]={ 0x1F647, 0x1F3FD, 0x200D, 0x2640 },
- ["woman bowing: medium-dark skin tone"]={ 0x1F647, 0x1F3FE, 0x200D, 0x2640 },
- ["woman bowing: medium-light skin tone"]={ 0x1F647, 0x1F3FC, 0x200D, 0x2640 },
- ["woman cartwheeling"]={ 0x1F938, 0x200D, 0x2640 },
- ["woman cartwheeling: dark skin tone"]={ 0x1F938, 0x1F3FF, 0x200D, 0x2640 },
- ["woman cartwheeling: light skin tone"]={ 0x1F938, 0x1F3FB, 0x200D, 0x2640 },
- ["woman cartwheeling: medium skin tone"]={ 0x1F938, 0x1F3FD, 0x200D, 0x2640 },
- ["woman cartwheeling: medium-dark skin tone"]={ 0x1F938, 0x1F3FE, 0x200D, 0x2640 },
- ["woman cartwheeling: medium-light skin tone"]={ 0x1F938, 0x1F3FC, 0x200D, 0x2640 },
- ["woman climbing"]={ 0x1F9D7, 0x200D, 0x2640 },
- ["woman climbing: dark skin tone"]={ 0x1F9D7, 0x1F3FF, 0x200D, 0x2640 },
- ["woman climbing: light skin tone"]={ 0x1F9D7, 0x1F3FB, 0x200D, 0x2640 },
- ["woman climbing: medium skin tone"]={ 0x1F9D7, 0x1F3FD, 0x200D, 0x2640 },
- ["woman climbing: medium-dark skin tone"]={ 0x1F9D7, 0x1F3FE, 0x200D, 0x2640 },
- ["woman climbing: medium-light skin tone"]={ 0x1F9D7, 0x1F3FC, 0x200D, 0x2640 },
- ["woman construction worker"]={ 0x1F477, 0x200D, 0x2640 },
- ["woman construction worker: dark skin tone"]={ 0x1F477, 0x1F3FF, 0x200D, 0x2640 },
- ["woman construction worker: light skin tone"]={ 0x1F477, 0x1F3FB, 0x200D, 0x2640 },
- ["woman construction worker: medium skin tone"]={ 0x1F477, 0x1F3FD, 0x200D, 0x2640 },
- ["woman construction worker: medium-dark skin tone"]={ 0x1F477, 0x1F3FE, 0x200D, 0x2640 },
- ["woman construction worker: medium-light skin tone"]={ 0x1F477, 0x1F3FC, 0x200D, 0x2640 },
+ ["woman biking"]={ 0x1F6B4, 0x200D, 0x2640, 0xFE0F },
+ ["woman biking: dark skin tone"]={ 0x1F6B4, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman biking: light skin tone"]={ 0x1F6B4, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman biking: medium skin tone"]={ 0x1F6B4, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman biking: medium-dark skin tone"]={ 0x1F6B4, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman biking: medium-light skin tone"]={ 0x1F6B4, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman bouncing ball"]={ 0x26F9, 0xFE0F, 0x200D, 0x2640, 0xFE0F },
+ ["woman bouncing ball: dark skin tone"]={ 0x26F9, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman bouncing ball: light skin tone"]={ 0x26F9, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman bouncing ball: medium skin tone"]={ 0x26F9, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman bouncing ball: medium-dark skin tone"]={ 0x26F9, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman bouncing ball: medium-light skin tone"]={ 0x26F9, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman bowing"]={ 0x1F647, 0x200D, 0x2640, 0xFE0F },
+ ["woman bowing: dark skin tone"]={ 0x1F647, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman bowing: light skin tone"]={ 0x1F647, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman bowing: medium skin tone"]={ 0x1F647, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman bowing: medium-dark skin tone"]={ 0x1F647, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman bowing: medium-light skin tone"]={ 0x1F647, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman cartwheeling"]={ 0x1F938, 0x200D, 0x2640, 0xFE0F },
+ ["woman cartwheeling: dark skin tone"]={ 0x1F938, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman cartwheeling: light skin tone"]={ 0x1F938, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman cartwheeling: medium skin tone"]={ 0x1F938, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman cartwheeling: medium-dark skin tone"]={ 0x1F938, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman cartwheeling: medium-light skin tone"]={ 0x1F938, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman climbing"]={ 0x1F9D7, 0x200D, 0x2640, 0xFE0F },
+ ["woman climbing: dark skin tone"]={ 0x1F9D7, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman climbing: light skin tone"]={ 0x1F9D7, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman climbing: medium skin tone"]={ 0x1F9D7, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman climbing: medium-dark skin tone"]={ 0x1F9D7, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman climbing: medium-light skin tone"]={ 0x1F9D7, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman construction worker"]={ 0x1F477, 0x200D, 0x2640, 0xFE0F },
+ ["woman construction worker: dark skin tone"]={ 0x1F477, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman construction worker: light skin tone"]={ 0x1F477, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman construction worker: medium skin tone"]={ 0x1F477, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman construction worker: medium-dark skin tone"]={ 0x1F477, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman construction worker: medium-light skin tone"]={ 0x1F477, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
["woman cook"]={ 0x1F469, 0x200D, 0x1F373 },
["woman cook: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F373 },
["woman cook: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F373 },
@@ -2325,36 +2624,36 @@ return {
["woman dancing: medium skin tone"]={ 0x1F483, 0x1F3FD },
["woman dancing: medium-dark skin tone"]={ 0x1F483, 0x1F3FE },
["woman dancing: medium-light skin tone"]={ 0x1F483, 0x1F3FC },
- ["woman detective"]={ 0x1F575, 0x200D, 0x2640 },
- ["woman detective: dark skin tone"]={ 0x1F575, 0x1F3FF, 0x200D, 0x2640 },
- ["woman detective: light skin tone"]={ 0x1F575, 0x1F3FB, 0x200D, 0x2640 },
- ["woman detective: medium skin tone"]={ 0x1F575, 0x1F3FD, 0x200D, 0x2640 },
- ["woman detective: medium-dark skin tone"]={ 0x1F575, 0x1F3FE, 0x200D, 0x2640 },
- ["woman detective: medium-light skin tone"]={ 0x1F575, 0x1F3FC, 0x200D, 0x2640 },
- ["woman elf"]={ 0x1F9DD, 0x200D, 0x2640 },
- ["woman elf: dark skin tone"]={ 0x1F9DD, 0x1F3FF, 0x200D, 0x2640 },
- ["woman elf: light skin tone"]={ 0x1F9DD, 0x1F3FB, 0x200D, 0x2640 },
- ["woman elf: medium skin tone"]={ 0x1F9DD, 0x1F3FD, 0x200D, 0x2640 },
- ["woman elf: medium-dark skin tone"]={ 0x1F9DD, 0x1F3FE, 0x200D, 0x2640 },
- ["woman elf: medium-light skin tone"]={ 0x1F9DD, 0x1F3FC, 0x200D, 0x2640 },
- ["woman facepalming"]={ 0x1F926, 0x200D, 0x2640 },
- ["woman facepalming: dark skin tone"]={ 0x1F926, 0x1F3FF, 0x200D, 0x2640 },
- ["woman facepalming: light skin tone"]={ 0x1F926, 0x1F3FB, 0x200D, 0x2640 },
- ["woman facepalming: medium skin tone"]={ 0x1F926, 0x1F3FD, 0x200D, 0x2640 },
- ["woman facepalming: medium-dark skin tone"]={ 0x1F926, 0x1F3FE, 0x200D, 0x2640 },
- ["woman facepalming: medium-light skin tone"]={ 0x1F926, 0x1F3FC, 0x200D, 0x2640 },
+ ["woman detective"]={ 0x1F575, 0xFE0F, 0x200D, 0x2640, 0xFE0F },
+ ["woman detective: dark skin tone"]={ 0x1F575, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman detective: light skin tone"]={ 0x1F575, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman detective: medium skin tone"]={ 0x1F575, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman detective: medium-dark skin tone"]={ 0x1F575, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman detective: medium-light skin tone"]={ 0x1F575, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman elf"]={ 0x1F9DD, 0x200D, 0x2640, 0xFE0F },
+ ["woman elf: dark skin tone"]={ 0x1F9DD, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman elf: light skin tone"]={ 0x1F9DD, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman elf: medium skin tone"]={ 0x1F9DD, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman elf: medium-dark skin tone"]={ 0x1F9DD, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman elf: medium-light skin tone"]={ 0x1F9DD, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman facepalming"]={ 0x1F926, 0x200D, 0x2640, 0xFE0F },
+ ["woman facepalming: dark skin tone"]={ 0x1F926, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman facepalming: light skin tone"]={ 0x1F926, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman facepalming: medium skin tone"]={ 0x1F926, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman facepalming: medium-dark skin tone"]={ 0x1F926, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman facepalming: medium-light skin tone"]={ 0x1F926, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
["woman factory worker"]={ 0x1F469, 0x200D, 0x1F3ED },
["woman factory worker: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F3ED },
["woman factory worker: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F3ED },
["woman factory worker: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F3ED },
["woman factory worker: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F3ED },
["woman factory worker: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F3ED },
- ["woman fairy"]={ 0x1F9DA, 0x200D, 0x2640 },
- ["woman fairy: dark skin tone"]={ 0x1F9DA, 0x1F3FF, 0x200D, 0x2640 },
- ["woman fairy: light skin tone"]={ 0x1F9DA, 0x1F3FB, 0x200D, 0x2640 },
- ["woman fairy: medium skin tone"]={ 0x1F9DA, 0x1F3FD, 0x200D, 0x2640 },
- ["woman fairy: medium-dark skin tone"]={ 0x1F9DA, 0x1F3FE, 0x200D, 0x2640 },
- ["woman fairy: medium-light skin tone"]={ 0x1F9DA, 0x1F3FC, 0x200D, 0x2640 },
+ ["woman fairy"]={ 0x1F9DA, 0x200D, 0x2640, 0xFE0F },
+ ["woman fairy: dark skin tone"]={ 0x1F9DA, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman fairy: light skin tone"]={ 0x1F9DA, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman fairy: medium skin tone"]={ 0x1F9DA, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman fairy: medium-dark skin tone"]={ 0x1F9DA, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman fairy: medium-light skin tone"]={ 0x1F9DA, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
["woman farmer"]={ 0x1F469, 0x200D, 0x1F33E },
["woman farmer: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F33E },
["woman farmer: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F33E },
@@ -2367,193 +2666,229 @@ return {
["woman firefighter: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F692 },
["woman firefighter: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F692 },
["woman firefighter: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F692 },
- ["woman frowning"]={ 0x1F64D, 0x200D, 0x2640 },
- ["woman frowning: dark skin tone"]={ 0x1F64D, 0x1F3FF, 0x200D, 0x2640 },
- ["woman frowning: light skin tone"]={ 0x1F64D, 0x1F3FB, 0x200D, 0x2640 },
- ["woman frowning: medium skin tone"]={ 0x1F64D, 0x1F3FD, 0x200D, 0x2640 },
- ["woman frowning: medium-dark skin tone"]={ 0x1F64D, 0x1F3FE, 0x200D, 0x2640 },
- ["woman frowning: medium-light skin tone"]={ 0x1F64D, 0x1F3FC, 0x200D, 0x2640 },
- ["woman genie"]={ 0x1F9DE, 0x200D, 0x2640 },
- ["woman gesturing no"]={ 0x1F645, 0x200D, 0x2640 },
- ["woman gesturing no: dark skin tone"]={ 0x1F645, 0x1F3FF, 0x200D, 0x2640 },
- ["woman gesturing no: light skin tone"]={ 0x1F645, 0x1F3FB, 0x200D, 0x2640 },
- ["woman gesturing no: medium skin tone"]={ 0x1F645, 0x1F3FD, 0x200D, 0x2640 },
- ["woman gesturing no: medium-dark skin tone"]={ 0x1F645, 0x1F3FE, 0x200D, 0x2640 },
- ["woman gesturing no: medium-light skin tone"]={ 0x1F645, 0x1F3FC, 0x200D, 0x2640 },
- ["woman gesturing ok"]={ 0x1F646, 0x200D, 0x2640 },
- ["woman gesturing ok: dark skin tone"]={ 0x1F646, 0x1F3FF, 0x200D, 0x2640 },
- ["woman gesturing ok: light skin tone"]={ 0x1F646, 0x1F3FB, 0x200D, 0x2640 },
- ["woman gesturing ok: medium skin tone"]={ 0x1F646, 0x1F3FD, 0x200D, 0x2640 },
- ["woman gesturing ok: medium-dark skin tone"]={ 0x1F646, 0x1F3FE, 0x200D, 0x2640 },
- ["woman gesturing ok: medium-light skin tone"]={ 0x1F646, 0x1F3FC, 0x200D, 0x2640 },
- ["woman getting haircut"]={ 0x1F487, 0x200D, 0x2640 },
- ["woman getting haircut: dark skin tone"]={ 0x1F487, 0x1F3FF, 0x200D, 0x2640 },
- ["woman getting haircut: light skin tone"]={ 0x1F487, 0x1F3FB, 0x200D, 0x2640 },
- ["woman getting haircut: medium skin tone"]={ 0x1F487, 0x1F3FD, 0x200D, 0x2640 },
- ["woman getting haircut: medium-dark skin tone"]={ 0x1F487, 0x1F3FE, 0x200D, 0x2640 },
- ["woman getting haircut: medium-light skin tone"]={ 0x1F487, 0x1F3FC, 0x200D, 0x2640 },
- ["woman getting massage"]={ 0x1F486, 0x200D, 0x2640 },
- ["woman getting massage: dark skin tone"]={ 0x1F486, 0x1F3FF, 0x200D, 0x2640 },
- ["woman getting massage: light skin tone"]={ 0x1F486, 0x1F3FB, 0x200D, 0x2640 },
- ["woman getting massage: medium skin tone"]={ 0x1F486, 0x1F3FD, 0x200D, 0x2640 },
- ["woman getting massage: medium-dark skin tone"]={ 0x1F486, 0x1F3FE, 0x200D, 0x2640 },
- ["woman getting massage: medium-light skin tone"]={ 0x1F486, 0x1F3FC, 0x200D, 0x2640 },
- ["woman golfing"]={ 0x1F3CC, 0x200D, 0x2640 },
- ["woman golfing: dark skin tone"]={ 0x1F3CC, 0x1F3FF, 0x200D, 0x2640 },
- ["woman golfing: light skin tone"]={ 0x1F3CC, 0x1F3FB, 0x200D, 0x2640 },
- ["woman golfing: medium skin tone"]={ 0x1F3CC, 0x1F3FD, 0x200D, 0x2640 },
- ["woman golfing: medium-dark skin tone"]={ 0x1F3CC, 0x1F3FE, 0x200D, 0x2640 },
- ["woman golfing: medium-light skin tone"]={ 0x1F3CC, 0x1F3FC, 0x200D, 0x2640 },
- ["woman guard"]={ 0x1F482, 0x200D, 0x2640 },
- ["woman guard: dark skin tone"]={ 0x1F482, 0x1F3FF, 0x200D, 0x2640 },
- ["woman guard: light skin tone"]={ 0x1F482, 0x1F3FB, 0x200D, 0x2640 },
- ["woman guard: medium skin tone"]={ 0x1F482, 0x1F3FD, 0x200D, 0x2640 },
- ["woman guard: medium-dark skin tone"]={ 0x1F482, 0x1F3FE, 0x200D, 0x2640 },
- ["woman guard: medium-light skin tone"]={ 0x1F482, 0x1F3FC, 0x200D, 0x2640 },
- ["woman health worker"]={ 0x1F469, 0x200D, 0x2695 },
- ["woman health worker: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2695 },
- ["woman health worker: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2695 },
- ["woman health worker: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x2695 },
- ["woman health worker: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x2695 },
- ["woman health worker: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x2695 },
- ["woman in lotus position"]={ 0x1F9D8, 0x200D, 0x2640 },
- ["woman in lotus position: dark skin tone"]={ 0x1F9D8, 0x1F3FF, 0x200D, 0x2640 },
- ["woman in lotus position: light skin tone"]={ 0x1F9D8, 0x1F3FB, 0x200D, 0x2640 },
- ["woman in lotus position: medium skin tone"]={ 0x1F9D8, 0x1F3FD, 0x200D, 0x2640 },
- ["woman in lotus position: medium-dark skin tone"]={ 0x1F9D8, 0x1F3FE, 0x200D, 0x2640 },
- ["woman in lotus position: medium-light skin tone"]={ 0x1F9D8, 0x1F3FC, 0x200D, 0x2640 },
- ["woman in steamy room"]={ 0x1F9D6, 0x200D, 0x2640 },
- ["woman in steamy room: dark skin tone"]={ 0x1F9D6, 0x1F3FF, 0x200D, 0x2640 },
- ["woman in steamy room: light skin tone"]={ 0x1F9D6, 0x1F3FB, 0x200D, 0x2640 },
- ["woman in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD, 0x200D, 0x2640 },
- ["woman in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE, 0x200D, 0x2640 },
- ["woman in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC, 0x200D, 0x2640 },
- ["woman judge"]={ 0x1F469, 0x200D, 0x2696 },
- ["woman judge: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2696 },
- ["woman judge: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2696 },
- ["woman judge: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x2696 },
- ["woman judge: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x2696 },
- ["woman judge: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x2696 },
- ["woman juggling"]={ 0x1F939, 0x200D, 0x2640 },
- ["woman juggling: dark skin tone"]={ 0x1F939, 0x1F3FF, 0x200D, 0x2640 },
- ["woman juggling: light skin tone"]={ 0x1F939, 0x1F3FB, 0x200D, 0x2640 },
- ["woman juggling: medium skin tone"]={ 0x1F939, 0x1F3FD, 0x200D, 0x2640 },
- ["woman juggling: medium-dark skin tone"]={ 0x1F939, 0x1F3FE, 0x200D, 0x2640 },
- ["woman juggling: medium-light skin tone"]={ 0x1F939, 0x1F3FC, 0x200D, 0x2640 },
- ["woman lifting weights"]={ 0x1F3CB, 0x200D, 0x2640 },
- ["woman lifting weights: dark skin tone"]={ 0x1F3CB, 0x1F3FF, 0x200D, 0x2640 },
- ["woman lifting weights: light skin tone"]={ 0x1F3CB, 0x1F3FB, 0x200D, 0x2640 },
- ["woman lifting weights: medium skin tone"]={ 0x1F3CB, 0x1F3FD, 0x200D, 0x2640 },
- ["woman lifting weights: medium-dark skin tone"]={ 0x1F3CB, 0x1F3FE, 0x200D, 0x2640 },
- ["woman lifting weights: medium-light skin tone"]={ 0x1F3CB, 0x1F3FC, 0x200D, 0x2640 },
- ["woman mage"]={ 0x1F9D9, 0x200D, 0x2640 },
- ["woman mage: dark skin tone"]={ 0x1F9D9, 0x1F3FF, 0x200D, 0x2640 },
- ["woman mage: light skin tone"]={ 0x1F9D9, 0x1F3FB, 0x200D, 0x2640 },
- ["woman mage: medium skin tone"]={ 0x1F9D9, 0x1F3FD, 0x200D, 0x2640 },
- ["woman mage: medium-dark skin tone"]={ 0x1F9D9, 0x1F3FE, 0x200D, 0x2640 },
- ["woman mage: medium-light skin tone"]={ 0x1F9D9, 0x1F3FC, 0x200D, 0x2640 },
+ ["woman frowning"]={ 0x1F64D, 0x200D, 0x2640, 0xFE0F },
+ ["woman frowning: dark skin tone"]={ 0x1F64D, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman frowning: light skin tone"]={ 0x1F64D, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman frowning: medium skin tone"]={ 0x1F64D, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman frowning: medium-dark skin tone"]={ 0x1F64D, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman frowning: medium-light skin tone"]={ 0x1F64D, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman genie"]={ 0x1F9DE, 0x200D, 0x2640, 0xFE0F },
+ ["woman gesturing no"]={ 0x1F645, 0x200D, 0x2640, 0xFE0F },
+ ["woman gesturing no: dark skin tone"]={ 0x1F645, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman gesturing no: light skin tone"]={ 0x1F645, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman gesturing no: medium skin tone"]={ 0x1F645, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman gesturing no: medium-dark skin tone"]={ 0x1F645, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman gesturing no: medium-light skin tone"]={ 0x1F645, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman gesturing ok"]={ 0x1F646, 0x200D, 0x2640, 0xFE0F },
+ ["woman gesturing ok: dark skin tone"]={ 0x1F646, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman gesturing ok: light skin tone"]={ 0x1F646, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman gesturing ok: medium skin tone"]={ 0x1F646, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman gesturing ok: medium-dark skin tone"]={ 0x1F646, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman gesturing ok: medium-light skin tone"]={ 0x1F646, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman getting haircut"]={ 0x1F487, 0x200D, 0x2640, 0xFE0F },
+ ["woman getting haircut: dark skin tone"]={ 0x1F487, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman getting haircut: light skin tone"]={ 0x1F487, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman getting haircut: medium skin tone"]={ 0x1F487, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman getting haircut: medium-dark skin tone"]={ 0x1F487, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman getting haircut: medium-light skin tone"]={ 0x1F487, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman getting massage"]={ 0x1F486, 0x200D, 0x2640, 0xFE0F },
+ ["woman getting massage: dark skin tone"]={ 0x1F486, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman getting massage: light skin tone"]={ 0x1F486, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman getting massage: medium skin tone"]={ 0x1F486, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman getting massage: medium-dark skin tone"]={ 0x1F486, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman getting massage: medium-light skin tone"]={ 0x1F486, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman golfing"]={ 0x1F3CC, 0xFE0F, 0x200D, 0x2640, 0xFE0F },
+ ["woman golfing: dark skin tone"]={ 0x1F3CC, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman golfing: light skin tone"]={ 0x1F3CC, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman golfing: medium skin tone"]={ 0x1F3CC, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman golfing: medium-dark skin tone"]={ 0x1F3CC, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman golfing: medium-light skin tone"]={ 0x1F3CC, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman guard"]={ 0x1F482, 0x200D, 0x2640, 0xFE0F },
+ ["woman guard: dark skin tone"]={ 0x1F482, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman guard: light skin tone"]={ 0x1F482, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman guard: medium skin tone"]={ 0x1F482, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman guard: medium-dark skin tone"]={ 0x1F482, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman guard: medium-light skin tone"]={ 0x1F482, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman health worker"]={ 0x1F469, 0x200D, 0x2695, 0xFE0F },
+ ["woman health worker: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2695, 0xFE0F },
+ ["woman health worker: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2695, 0xFE0F },
+ ["woman health worker: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x2695, 0xFE0F },
+ ["woman health worker: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x2695, 0xFE0F },
+ ["woman health worker: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x2695, 0xFE0F },
+ ["woman in lotus position"]={ 0x1F9D8, 0x200D, 0x2640, 0xFE0F },
+ ["woman in lotus position: dark skin tone"]={ 0x1F9D8, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman in lotus position: light skin tone"]={ 0x1F9D8, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman in lotus position: medium skin tone"]={ 0x1F9D8, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman in lotus position: medium-dark skin tone"]={ 0x1F9D8, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman in lotus position: medium-light skin tone"]={ 0x1F9D8, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman in manual wheelchair"]={ 0x1F469, 0x200D, 0x1F9BD },
+ ["woman in manual wheelchair: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9BD },
+ ["woman in manual wheelchair: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9BD },
+ ["woman in manual wheelchair: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9BD },
+ ["woman in manual wheelchair: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9BD },
+ ["woman in manual wheelchair: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9BD },
+ ["woman in motorized wheelchair"]={ 0x1F469, 0x200D, 0x1F9BC },
+ ["woman in motorized wheelchair: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9BC },
+ ["woman in motorized wheelchair: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9BC },
+ ["woman in motorized wheelchair: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9BC },
+ ["woman in motorized wheelchair: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9BC },
+ ["woman in motorized wheelchair: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9BC },
+ ["woman in steamy room"]={ 0x1F9D6, 0x200D, 0x2640, 0xFE0F },
+ ["woman in steamy room: dark skin tone"]={ 0x1F9D6, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman in steamy room: light skin tone"]={ 0x1F9D6, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman in steamy room: medium skin tone"]={ 0x1F9D6, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman in steamy room: medium-dark skin tone"]={ 0x1F9D6, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman in steamy room: medium-light skin tone"]={ 0x1F9D6, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman judge"]={ 0x1F469, 0x200D, 0x2696, 0xFE0F },
+ ["woman judge: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2696, 0xFE0F },
+ ["woman judge: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2696, 0xFE0F },
+ ["woman judge: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x2696, 0xFE0F },
+ ["woman judge: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x2696, 0xFE0F },
+ ["woman judge: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x2696, 0xFE0F },
+ ["woman juggling"]={ 0x1F939, 0x200D, 0x2640, 0xFE0F },
+ ["woman juggling: dark skin tone"]={ 0x1F939, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman juggling: light skin tone"]={ 0x1F939, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman juggling: medium skin tone"]={ 0x1F939, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman juggling: medium-dark skin tone"]={ 0x1F939, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman juggling: medium-light skin tone"]={ 0x1F939, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman kneeling"]={ 0x1F9CE, 0x200D, 0x2640, 0xFE0F },
+ ["woman kneeling: dark skin tone"]={ 0x1F9CE, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman kneeling: light skin tone"]={ 0x1F9CE, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman kneeling: medium skin tone"]={ 0x1F9CE, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman kneeling: medium-dark skin tone"]={ 0x1F9CE, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman kneeling: medium-light skin tone"]={ 0x1F9CE, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman lifting weights"]={ 0x1F3CB, 0xFE0F, 0x200D, 0x2640, 0xFE0F },
+ ["woman lifting weights: dark skin tone"]={ 0x1F3CB, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman lifting weights: light skin tone"]={ 0x1F3CB, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman lifting weights: medium skin tone"]={ 0x1F3CB, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman lifting weights: medium-dark skin tone"]={ 0x1F3CB, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman lifting weights: medium-light skin tone"]={ 0x1F3CB, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman mage"]={ 0x1F9D9, 0x200D, 0x2640, 0xFE0F },
+ ["woman mage: dark skin tone"]={ 0x1F9D9, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman mage: light skin tone"]={ 0x1F9D9, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman mage: medium skin tone"]={ 0x1F9D9, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman mage: medium-dark skin tone"]={ 0x1F9D9, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman mage: medium-light skin tone"]={ 0x1F9D9, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
["woman mechanic"]={ 0x1F469, 0x200D, 0x1F527 },
["woman mechanic: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F527 },
["woman mechanic: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F527 },
["woman mechanic: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F527 },
["woman mechanic: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F527 },
["woman mechanic: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F527 },
- ["woman mountain biking"]={ 0x1F6B5, 0x200D, 0x2640 },
- ["woman mountain biking: dark skin tone"]={ 0x1F6B5, 0x1F3FF, 0x200D, 0x2640 },
- ["woman mountain biking: light skin tone"]={ 0x1F6B5, 0x1F3FB, 0x200D, 0x2640 },
- ["woman mountain biking: medium skin tone"]={ 0x1F6B5, 0x1F3FD, 0x200D, 0x2640 },
- ["woman mountain biking: medium-dark skin tone"]={ 0x1F6B5, 0x1F3FE, 0x200D, 0x2640 },
- ["woman mountain biking: medium-light skin tone"]={ 0x1F6B5, 0x1F3FC, 0x200D, 0x2640 },
+ ["woman mountain biking"]={ 0x1F6B5, 0x200D, 0x2640, 0xFE0F },
+ ["woman mountain biking: dark skin tone"]={ 0x1F6B5, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman mountain biking: light skin tone"]={ 0x1F6B5, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman mountain biking: medium skin tone"]={ 0x1F6B5, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman mountain biking: medium-dark skin tone"]={ 0x1F6B5, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman mountain biking: medium-light skin tone"]={ 0x1F6B5, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
["woman office worker"]={ 0x1F469, 0x200D, 0x1F4BC },
["woman office worker: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F4BC },
["woman office worker: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F4BC },
["woman office worker: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F4BC },
["woman office worker: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F4BC },
["woman office worker: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F4BC },
- ["woman pilot"]={ 0x1F469, 0x200D, 0x2708 },
- ["woman pilot: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2708 },
- ["woman pilot: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2708 },
- ["woman pilot: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x2708 },
- ["woman pilot: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x2708 },
- ["woman pilot: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x2708 },
- ["woman playing handball"]={ 0x1F93E, 0x200D, 0x2640 },
- ["woman playing handball: dark skin tone"]={ 0x1F93E, 0x1F3FF, 0x200D, 0x2640 },
- ["woman playing handball: light skin tone"]={ 0x1F93E, 0x1F3FB, 0x200D, 0x2640 },
- ["woman playing handball: medium skin tone"]={ 0x1F93E, 0x1F3FD, 0x200D, 0x2640 },
- ["woman playing handball: medium-dark skin tone"]={ 0x1F93E, 0x1F3FE, 0x200D, 0x2640 },
- ["woman playing handball: medium-light skin tone"]={ 0x1F93E, 0x1F3FC, 0x200D, 0x2640 },
- ["woman playing water polo"]={ 0x1F93D, 0x200D, 0x2640 },
- ["woman playing water polo: dark skin tone"]={ 0x1F93D, 0x1F3FF, 0x200D, 0x2640 },
- ["woman playing water polo: light skin tone"]={ 0x1F93D, 0x1F3FB, 0x200D, 0x2640 },
- ["woman playing water polo: medium skin tone"]={ 0x1F93D, 0x1F3FD, 0x200D, 0x2640 },
- ["woman playing water polo: medium-dark skin tone"]={ 0x1F93D, 0x1F3FE, 0x200D, 0x2640 },
- ["woman playing water polo: medium-light skin tone"]={ 0x1F93D, 0x1F3FC, 0x200D, 0x2640 },
- ["woman police officer"]={ 0x1F46E, 0x200D, 0x2640 },
- ["woman police officer: dark skin tone"]={ 0x1F46E, 0x1F3FF, 0x200D, 0x2640 },
- ["woman police officer: light skin tone"]={ 0x1F46E, 0x1F3FB, 0x200D, 0x2640 },
- ["woman police officer: medium skin tone"]={ 0x1F46E, 0x1F3FD, 0x200D, 0x2640 },
- ["woman police officer: medium-dark skin tone"]={ 0x1F46E, 0x1F3FE, 0x200D, 0x2640 },
- ["woman police officer: medium-light skin tone"]={ 0x1F46E, 0x1F3FC, 0x200D, 0x2640 },
- ["woman pouting"]={ 0x1F64E, 0x200D, 0x2640 },
- ["woman pouting: dark skin tone"]={ 0x1F64E, 0x1F3FF, 0x200D, 0x2640 },
- ["woman pouting: light skin tone"]={ 0x1F64E, 0x1F3FB, 0x200D, 0x2640 },
- ["woman pouting: medium skin tone"]={ 0x1F64E, 0x1F3FD, 0x200D, 0x2640 },
- ["woman pouting: medium-dark skin tone"]={ 0x1F64E, 0x1F3FE, 0x200D, 0x2640 },
- ["woman pouting: medium-light skin tone"]={ 0x1F64E, 0x1F3FC, 0x200D, 0x2640 },
- ["woman raising hand"]={ 0x1F64B, 0x200D, 0x2640 },
- ["woman raising hand: dark skin tone"]={ 0x1F64B, 0x1F3FF, 0x200D, 0x2640 },
- ["woman raising hand: light skin tone"]={ 0x1F64B, 0x1F3FB, 0x200D, 0x2640 },
- ["woman raising hand: medium skin tone"]={ 0x1F64B, 0x1F3FD, 0x200D, 0x2640 },
- ["woman raising hand: medium-dark skin tone"]={ 0x1F64B, 0x1F3FE, 0x200D, 0x2640 },
- ["woman raising hand: medium-light skin tone"]={ 0x1F64B, 0x1F3FC, 0x200D, 0x2640 },
- ["woman rowing boat"]={ 0x1F6A3, 0x200D, 0x2640 },
- ["woman rowing boat: dark skin tone"]={ 0x1F6A3, 0x1F3FF, 0x200D, 0x2640 },
- ["woman rowing boat: light skin tone"]={ 0x1F6A3, 0x1F3FB, 0x200D, 0x2640 },
- ["woman rowing boat: medium skin tone"]={ 0x1F6A3, 0x1F3FD, 0x200D, 0x2640 },
- ["woman rowing boat: medium-dark skin tone"]={ 0x1F6A3, 0x1F3FE, 0x200D, 0x2640 },
- ["woman rowing boat: medium-light skin tone"]={ 0x1F6A3, 0x1F3FC, 0x200D, 0x2640 },
- ["woman running"]={ 0x1F3C3, 0x200D, 0x2640 },
- ["woman running: dark skin tone"]={ 0x1F3C3, 0x1F3FF, 0x200D, 0x2640 },
- ["woman running: light skin tone"]={ 0x1F3C3, 0x1F3FB, 0x200D, 0x2640 },
- ["woman running: medium skin tone"]={ 0x1F3C3, 0x1F3FD, 0x200D, 0x2640 },
- ["woman running: medium-dark skin tone"]={ 0x1F3C3, 0x1F3FE, 0x200D, 0x2640 },
- ["woman running: medium-light skin tone"]={ 0x1F3C3, 0x1F3FC, 0x200D, 0x2640 },
+ ["woman pilot"]={ 0x1F469, 0x200D, 0x2708, 0xFE0F },
+ ["woman pilot: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x2708, 0xFE0F },
+ ["woman pilot: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x2708, 0xFE0F },
+ ["woman pilot: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x2708, 0xFE0F },
+ ["woman pilot: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x2708, 0xFE0F },
+ ["woman pilot: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x2708, 0xFE0F },
+ ["woman playing handball"]={ 0x1F93E, 0x200D, 0x2640, 0xFE0F },
+ ["woman playing handball: dark skin tone"]={ 0x1F93E, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman playing handball: light skin tone"]={ 0x1F93E, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman playing handball: medium skin tone"]={ 0x1F93E, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman playing handball: medium-dark skin tone"]={ 0x1F93E, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman playing handball: medium-light skin tone"]={ 0x1F93E, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman playing water polo"]={ 0x1F93D, 0x200D, 0x2640, 0xFE0F },
+ ["woman playing water polo: dark skin tone"]={ 0x1F93D, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman playing water polo: light skin tone"]={ 0x1F93D, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman playing water polo: medium skin tone"]={ 0x1F93D, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman playing water polo: medium-dark skin tone"]={ 0x1F93D, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman playing water polo: medium-light skin tone"]={ 0x1F93D, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman police officer"]={ 0x1F46E, 0x200D, 0x2640, 0xFE0F },
+ ["woman police officer: dark skin tone"]={ 0x1F46E, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman police officer: light skin tone"]={ 0x1F46E, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman police officer: medium skin tone"]={ 0x1F46E, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman police officer: medium-dark skin tone"]={ 0x1F46E, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman police officer: medium-light skin tone"]={ 0x1F46E, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman pouting"]={ 0x1F64E, 0x200D, 0x2640, 0xFE0F },
+ ["woman pouting: dark skin tone"]={ 0x1F64E, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman pouting: light skin tone"]={ 0x1F64E, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman pouting: medium skin tone"]={ 0x1F64E, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman pouting: medium-dark skin tone"]={ 0x1F64E, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman pouting: medium-light skin tone"]={ 0x1F64E, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman raising hand"]={ 0x1F64B, 0x200D, 0x2640, 0xFE0F },
+ ["woman raising hand: dark skin tone"]={ 0x1F64B, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman raising hand: light skin tone"]={ 0x1F64B, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman raising hand: medium skin tone"]={ 0x1F64B, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman raising hand: medium-dark skin tone"]={ 0x1F64B, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman raising hand: medium-light skin tone"]={ 0x1F64B, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman rowing boat"]={ 0x1F6A3, 0x200D, 0x2640, 0xFE0F },
+ ["woman rowing boat: dark skin tone"]={ 0x1F6A3, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman rowing boat: light skin tone"]={ 0x1F6A3, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman rowing boat: medium skin tone"]={ 0x1F6A3, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman rowing boat: medium-dark skin tone"]={ 0x1F6A3, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman rowing boat: medium-light skin tone"]={ 0x1F6A3, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman running"]={ 0x1F3C3, 0x200D, 0x2640, 0xFE0F },
+ ["woman running: dark skin tone"]={ 0x1F3C3, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman running: light skin tone"]={ 0x1F3C3, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman running: medium skin tone"]={ 0x1F3C3, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman running: medium-dark skin tone"]={ 0x1F3C3, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman running: medium-light skin tone"]={ 0x1F3C3, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
["woman scientist"]={ 0x1F469, 0x200D, 0x1F52C },
["woman scientist: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F52C },
["woman scientist: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F52C },
["woman scientist: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F52C },
["woman scientist: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F52C },
["woman scientist: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F52C },
- ["woman shrugging"]={ 0x1F937, 0x200D, 0x2640 },
- ["woman shrugging: dark skin tone"]={ 0x1F937, 0x1F3FF, 0x200D, 0x2640 },
- ["woman shrugging: light skin tone"]={ 0x1F937, 0x1F3FB, 0x200D, 0x2640 },
- ["woman shrugging: medium skin tone"]={ 0x1F937, 0x1F3FD, 0x200D, 0x2640 },
- ["woman shrugging: medium-dark skin tone"]={ 0x1F937, 0x1F3FE, 0x200D, 0x2640 },
- ["woman shrugging: medium-light skin tone"]={ 0x1F937, 0x1F3FC, 0x200D, 0x2640 },
+ ["woman shrugging"]={ 0x1F937, 0x200D, 0x2640, 0xFE0F },
+ ["woman shrugging: dark skin tone"]={ 0x1F937, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman shrugging: light skin tone"]={ 0x1F937, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman shrugging: medium skin tone"]={ 0x1F937, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman shrugging: medium-dark skin tone"]={ 0x1F937, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman shrugging: medium-light skin tone"]={ 0x1F937, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
["woman singer"]={ 0x1F469, 0x200D, 0x1F3A4 },
["woman singer: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F3A4 },
["woman singer: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F3A4 },
["woman singer: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F3A4 },
["woman singer: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F3A4 },
["woman singer: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F3A4 },
+ ["woman standing"]={ 0x1F9CD, 0x200D, 0x2640, 0xFE0F },
+ ["woman standing: dark skin tone"]={ 0x1F9CD, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman standing: light skin tone"]={ 0x1F9CD, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman standing: medium skin tone"]={ 0x1F9CD, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman standing: medium-dark skin tone"]={ 0x1F9CD, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman standing: medium-light skin tone"]={ 0x1F9CD, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
["woman student"]={ 0x1F469, 0x200D, 0x1F393 },
["woman student: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F393 },
["woman student: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F393 },
["woman student: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F393 },
["woman student: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F393 },
["woman student: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F393 },
- ["woman surfing"]={ 0x1F3C4, 0x200D, 0x2640 },
- ["woman surfing: dark skin tone"]={ 0x1F3C4, 0x1F3FF, 0x200D, 0x2640 },
- ["woman surfing: light skin tone"]={ 0x1F3C4, 0x1F3FB, 0x200D, 0x2640 },
- ["woman surfing: medium skin tone"]={ 0x1F3C4, 0x1F3FD, 0x200D, 0x2640 },
- ["woman surfing: medium-dark skin tone"]={ 0x1F3C4, 0x1F3FE, 0x200D, 0x2640 },
- ["woman surfing: medium-light skin tone"]={ 0x1F3C4, 0x1F3FC, 0x200D, 0x2640 },
- ["woman swimming"]={ 0x1F3CA, 0x200D, 0x2640 },
- ["woman swimming: dark skin tone"]={ 0x1F3CA, 0x1F3FF, 0x200D, 0x2640 },
- ["woman swimming: light skin tone"]={ 0x1F3CA, 0x1F3FB, 0x200D, 0x2640 },
- ["woman swimming: medium skin tone"]={ 0x1F3CA, 0x1F3FD, 0x200D, 0x2640 },
- ["woman swimming: medium-dark skin tone"]={ 0x1F3CA, 0x1F3FE, 0x200D, 0x2640 },
- ["woman swimming: medium-light skin tone"]={ 0x1F3CA, 0x1F3FC, 0x200D, 0x2640 },
+ ["woman superhero"]={ 0x1F9B8, 0x200D, 0x2640, 0xFE0F },
+ ["woman superhero: dark skin tone"]={ 0x1F9B8, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman superhero: light skin tone"]={ 0x1F9B8, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman superhero: medium skin tone"]={ 0x1F9B8, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman superhero: medium-dark skin tone"]={ 0x1F9B8, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman superhero: medium-light skin tone"]={ 0x1F9B8, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman supervillain"]={ 0x1F9B9, 0x200D, 0x2640, 0xFE0F },
+ ["woman supervillain: dark skin tone"]={ 0x1F9B9, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman supervillain: light skin tone"]={ 0x1F9B9, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman supervillain: medium skin tone"]={ 0x1F9B9, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman supervillain: medium-dark skin tone"]={ 0x1F9B9, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman supervillain: medium-light skin tone"]={ 0x1F9B9, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman surfing"]={ 0x1F3C4, 0x200D, 0x2640, 0xFE0F },
+ ["woman surfing: dark skin tone"]={ 0x1F3C4, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman surfing: light skin tone"]={ 0x1F3C4, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman surfing: medium skin tone"]={ 0x1F3C4, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman surfing: medium-dark skin tone"]={ 0x1F3C4, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman surfing: medium-light skin tone"]={ 0x1F3C4, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman swimming"]={ 0x1F3CA, 0x200D, 0x2640, 0xFE0F },
+ ["woman swimming: dark skin tone"]={ 0x1F3CA, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman swimming: light skin tone"]={ 0x1F3CA, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman swimming: medium skin tone"]={ 0x1F3CA, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman swimming: medium-dark skin tone"]={ 0x1F3CA, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman swimming: medium-light skin tone"]={ 0x1F3CA, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
["woman teacher"]={ 0x1F469, 0x200D, 0x1F3EB },
["woman teacher: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F3EB },
["woman teacher: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F3EB },
@@ -2566,68 +2901,123 @@ return {
["woman technologist: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F4BB },
["woman technologist: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F4BB },
["woman technologist: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F4BB },
- ["woman tipping hand"]={ 0x1F481, 0x200D, 0x2640 },
- ["woman tipping hand: dark skin tone"]={ 0x1F481, 0x1F3FF, 0x200D, 0x2640 },
- ["woman tipping hand: light skin tone"]={ 0x1F481, 0x1F3FB, 0x200D, 0x2640 },
- ["woman tipping hand: medium skin tone"]={ 0x1F481, 0x1F3FD, 0x200D, 0x2640 },
- ["woman tipping hand: medium-dark skin tone"]={ 0x1F481, 0x1F3FE, 0x200D, 0x2640 },
- ["woman tipping hand: medium-light skin tone"]={ 0x1F481, 0x1F3FC, 0x200D, 0x2640 },
- ["woman vampire"]={ 0x1F9DB, 0x200D, 0x2640 },
- ["woman vampire: dark skin tone"]={ 0x1F9DB, 0x1F3FF, 0x200D, 0x2640 },
- ["woman vampire: light skin tone"]={ 0x1F9DB, 0x1F3FB, 0x200D, 0x2640 },
- ["woman vampire: medium skin tone"]={ 0x1F9DB, 0x1F3FD, 0x200D, 0x2640 },
- ["woman vampire: medium-dark skin tone"]={ 0x1F9DB, 0x1F3FE, 0x200D, 0x2640 },
- ["woman vampire: medium-light skin tone"]={ 0x1F9DB, 0x1F3FC, 0x200D, 0x2640 },
- ["woman walking"]={ 0x1F6B6, 0x200D, 0x2640 },
- ["woman walking: dark skin tone"]={ 0x1F6B6, 0x1F3FF, 0x200D, 0x2640 },
- ["woman walking: light skin tone"]={ 0x1F6B6, 0x1F3FB, 0x200D, 0x2640 },
- ["woman walking: medium skin tone"]={ 0x1F6B6, 0x1F3FD, 0x200D, 0x2640 },
- ["woman walking: medium-dark skin tone"]={ 0x1F6B6, 0x1F3FE, 0x200D, 0x2640 },
- ["woman walking: medium-light skin tone"]={ 0x1F6B6, 0x1F3FC, 0x200D, 0x2640 },
- ["woman wearing turban"]={ 0x1F473, 0x200D, 0x2640 },
- ["woman wearing turban: dark skin tone"]={ 0x1F473, 0x1F3FF, 0x200D, 0x2640 },
- ["woman wearing turban: light skin tone"]={ 0x1F473, 0x1F3FB, 0x200D, 0x2640 },
- ["woman wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD, 0x200D, 0x2640 },
- ["woman wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE, 0x200D, 0x2640 },
- ["woman wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC, 0x200D, 0x2640 },
+ ["woman tipping hand"]={ 0x1F481, 0x200D, 0x2640, 0xFE0F },
+ ["woman tipping hand: dark skin tone"]={ 0x1F481, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman tipping hand: light skin tone"]={ 0x1F481, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman tipping hand: medium skin tone"]={ 0x1F481, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman tipping hand: medium-dark skin tone"]={ 0x1F481, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman tipping hand: medium-light skin tone"]={ 0x1F481, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman vampire"]={ 0x1F9DB, 0x200D, 0x2640, 0xFE0F },
+ ["woman vampire: dark skin tone"]={ 0x1F9DB, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman vampire: light skin tone"]={ 0x1F9DB, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman vampire: medium skin tone"]={ 0x1F9DB, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman vampire: medium-dark skin tone"]={ 0x1F9DB, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman vampire: medium-light skin tone"]={ 0x1F9DB, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman walking"]={ 0x1F6B6, 0x200D, 0x2640, 0xFE0F },
+ ["woman walking: dark skin tone"]={ 0x1F6B6, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman walking: light skin tone"]={ 0x1F6B6, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman walking: medium skin tone"]={ 0x1F6B6, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman walking: medium-dark skin tone"]={ 0x1F6B6, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman walking: medium-light skin tone"]={ 0x1F6B6, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman wearing turban"]={ 0x1F473, 0x200D, 0x2640, 0xFE0F },
+ ["woman wearing turban: dark skin tone"]={ 0x1F473, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman wearing turban: light skin tone"]={ 0x1F473, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman wearing turban: medium skin tone"]={ 0x1F473, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman wearing turban: medium-dark skin tone"]={ 0x1F473, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman wearing turban: medium-light skin tone"]={ 0x1F473, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
["woman with headscarf"]={ 0x1F9D5 },
["woman with headscarf: dark skin tone"]={ 0x1F9D5, 0x1F3FF },
["woman with headscarf: light skin tone"]={ 0x1F9D5, 0x1F3FB },
["woman with headscarf: medium skin tone"]={ 0x1F9D5, 0x1F3FD },
["woman with headscarf: medium-dark skin tone"]={ 0x1F9D5, 0x1F3FE },
["woman with headscarf: medium-light skin tone"]={ 0x1F9D5, 0x1F3FC },
- ["woman zombie"]={ 0x1F9DF, 0x200D, 0x2640 },
+ ["woman with probing cane"]={ 0x1F469, 0x200D, 0x1F9AF },
+ ["woman with probing cane: dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9AF },
+ ["woman with probing cane: light skin tone"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9AF },
+ ["woman with probing cane: medium skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9AF },
+ ["woman with probing cane: medium-dark skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9AF },
+ ["woman with probing cane: medium-light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9AF },
+ ["woman zombie"]={ 0x1F9DF, 0x200D, 0x2640, 0xFE0F },
+ ["woman: bald"]={ 0x1F469, 0x200D, 0x1F9B2 },
+ ["woman: blond hair"]={ 0x1F471, 0x200D, 0x2640, 0xFE0F },
+ ["woman: curly hair"]={ 0x1F469, 0x200D, 0x1F9B1 },
["woman: dark skin tone"]={ 0x1F469, 0x1F3FF },
+ ["woman: dark skin tone, bald"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9B2 },
+ ["woman: dark skin tone, blond hair"]={ 0x1F471, 0x1F3FF, 0x200D, 0x2640, 0xFE0F },
+ ["woman: dark skin tone, curly hair"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9B1 },
+ ["woman: dark skin tone, red hair"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9B0 },
+ ["woman: dark skin tone, white hair"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F9B3 },
["woman: light skin tone"]={ 0x1F469, 0x1F3FB },
+ ["woman: light skin tone, bald"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9B2 },
+ ["woman: light skin tone, blond hair"]={ 0x1F471, 0x1F3FB, 0x200D, 0x2640, 0xFE0F },
+ ["woman: light skin tone, curly hair"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9B1 },
+ ["woman: light skin tone, red hair"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9B0 },
+ ["woman: light skin tone, white hair"]={ 0x1F469, 0x1F3FB, 0x200D, 0x1F9B3 },
["woman: medium skin tone"]={ 0x1F469, 0x1F3FD },
+ ["woman: medium skin tone, bald"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9B2 },
+ ["woman: medium skin tone, blond hair"]={ 0x1F471, 0x1F3FD, 0x200D, 0x2640, 0xFE0F },
+ ["woman: medium skin tone, curly hair"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9B1 },
+ ["woman: medium skin tone, red hair"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9B0 },
+ ["woman: medium skin tone, white hair"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F9B3 },
["woman: medium-dark skin tone"]={ 0x1F469, 0x1F3FE },
+ ["woman: medium-dark skin tone, bald"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9B2 },
+ ["woman: medium-dark skin tone, blond hair"]={ 0x1F471, 0x1F3FE, 0x200D, 0x2640, 0xFE0F },
+ ["woman: medium-dark skin tone, curly hair"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9B1 },
+ ["woman: medium-dark skin tone, red hair"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9B0 },
+ ["woman: medium-dark skin tone, white hair"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F9B3 },
["woman: medium-light skin tone"]={ 0x1F469, 0x1F3FC },
+ ["woman: medium-light skin tone, bald"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9B2 },
+ ["woman: medium-light skin tone, blond hair"]={ 0x1F471, 0x1F3FC, 0x200D, 0x2640, 0xFE0F },
+ ["woman: medium-light skin tone, curly hair"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9B1 },
+ ["woman: medium-light skin tone, red hair"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9B0 },
+ ["woman: medium-light skin tone, white hair"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F9B3 },
+ ["woman: red hair"]={ 0x1F469, 0x200D, 0x1F9B0 },
+ ["woman: white hair"]={ 0x1F469, 0x200D, 0x1F9B3 },
["woman’s boot"]={ 0x1F462 },
["woman’s clothes"]={ 0x1F45A },
["woman’s hat"]={ 0x1F452 },
["woman’s sandal"]={ 0x1F461 },
- ["women with bunny ears partying"]={ 0x1F46F, 0x200D, 0x2640 },
- ["women wrestling"]={ 0x1F93C, 0x200D, 0x2640 },
+ ["women holding hands"]={ 0x1F46D },
+ ["women holding hands: dark skin tone"]={ 0x1F46D, 0x1F3FF },
+ ["women holding hands: dark skin tone, light skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB },
+ ["women holding hands: dark skin tone, medium skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FD },
+ ["women holding hands: dark skin tone, medium-dark skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FE },
+ ["women holding hands: dark skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FF, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC },
+ ["women holding hands: light skin tone"]={ 0x1F46D, 0x1F3FB },
+ ["women holding hands: medium skin tone"]={ 0x1F46D, 0x1F3FD },
+ ["women holding hands: medium skin tone, light skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB },
+ ["women holding hands: medium skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FD, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC },
+ ["women holding hands: medium-dark skin tone"]={ 0x1F46D, 0x1F3FE },
+ ["women holding hands: medium-dark skin tone, light skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB },
+ ["women holding hands: medium-dark skin tone, medium skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FD },
+ ["women holding hands: medium-dark skin tone, medium-light skin tone"]={ 0x1F469, 0x1F3FE, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FC },
+ ["women holding hands: medium-light skin tone"]={ 0x1F46D, 0x1F3FC },
+ ["women holding hands: medium-light skin tone, light skin tone"]={ 0x1F469, 0x1F3FC, 0x200D, 0x1F91D, 0x200D, 0x1F469, 0x1F3FB },
+ ["women with bunny ears"]={ 0x1F46F, 0x200D, 0x2640, 0xFE0F },
+ ["women wrestling"]={ 0x1F93C, 0x200D, 0x2640, 0xFE0F },
["women’s room"]={ 0x1F6BA },
- ["world map"]={ 0x1F5FA },
+ ["woozy face"]={ 0x1F974 },
+ ["world map"]={ 0x1F5FA, 0xFE0F },
["worried face"]={ 0x1F61F },
["wrapped gift"]={ 0x1F381 },
["wrench"]={ 0x1F527 },
- ["writing hand"]={ 0x270D },
+ ["writing hand"]={ 0x270D, 0xFE0F },
["writing hand: dark skin tone"]={ 0x270D, 0x1F3FF },
["writing hand: light skin tone"]={ 0x270D, 0x1F3FB },
["writing hand: medium skin tone"]={ 0x270D, 0x1F3FD },
["writing hand: medium-dark skin tone"]={ 0x270D, 0x1F3FE },
["writing hand: medium-light skin tone"]={ 0x270D, 0x1F3FC },
+ ["yarn"]={ 0x1F9F6 },
+ ["yawning face"]={ 0x1F971 },
+ ["yellow circle"]={ 0x1F7E1 },
["yellow heart"]={ 0x1F49B },
- ["yemen"]={ 0x1F1FE, 0x1F1EA },
+ ["yellow square"]={ 0x1F7E8 },
["yen banknote"]={ 0x1F4B4 },
- ["yin yang"]={ 0x262F },
- ["zambia"]={ 0x1F1FF, 0x1F1F2 },
+ ["yin yang"]={ 0x262F, 0xFE0F },
+ ["yo-yo"]={ 0x1FA80 },
+ ["zany face"]={ 0x1F92A },
["zebra"]={ 0x1F993 },
- ["zimbabwe"]={ 0x1F1FF, 0x1F1FC },
["zipper-mouth face"]={ 0x1F910 },
["zombie"]={ 0x1F9DF },
["zzz"]={ 0x1F4A4 },
- ["Åland islands"]={ 0x1F1E6, 0x1F1FD },
-}
+} \ No newline at end of file
diff --git a/tex/context/base/mkiv/char-ini.lua b/tex/context/base/mkiv/char-ini.lua
index c308a2c0f..fb9d9f126 100644
--- a/tex/context/base/mkiv/char-ini.lua
+++ b/tex/context/base/mkiv/char-ini.lua
@@ -234,6 +234,7 @@ local blocks = allocate {
["cham"] = { first = 0x0AA00, last = 0x0AA5F, description = "Cham" },
["cherokee"] = { first = 0x013A0, last = 0x013FF, otf="cher", description = "Cherokee" },
["cherokeesupplement"] = { first = 0x0AB70, last = 0x0ABBF, description = "Cherokee Supplement" },
+ ["chesssymbols"] = { first = 0x1FA00, last = 0x1FA6F, description = "Chess Symbols" },
["cjkcompatibility"] = { first = 0x03300, last = 0x033FF, otf="hang", description = "CJK Compatibility" },
["cjkcompatibilityforms"] = { first = 0x0FE30, last = 0x0FE4F, otf="hang", description = "CJK Compatibility Forms" },
["cjkcompatibilityideographs"] = { first = 0x0F900, last = 0x0FAFF, otf="hang", description = "CJK Compatibility Ideographs" },
@@ -296,6 +297,7 @@ local blocks = allocate {
-- ["digitsthai"] = { first = 0x00E50, last = 0x00E59, math = true },
-- ["digitstibetan"] = { first = 0x00F20, last = 0x00F29, math = true },
["dingbats"] = { first = 0x02700, last = 0x027BF, description = "Dingbats" },
+ ["dogra"] = { first = 0x11800, last = 0x1184F, description = "Dogra" },
["dominotiles"] = { first = 0x1F030, last = 0x1F09F, description = "Domino Tiles" },
["duployan"] = { first = 0x1BC00, last = 0x1BC9F, description = "Duployan" },
["earlydynasticcuneiform"] = { first = 0x12480, last = 0x1254F, description = "Early Dynastic Cuneiform" },
@@ -314,6 +316,7 @@ local blocks = allocate {
["geometricshapes"] = { first = 0x025A0, last = 0x025FF, math = true, description = "Geometric Shapes" },
["geometricshapesextended"] = { first = 0x1F780, last = 0x1F7FF, description = "Geometric Shapes Extended" },
["georgian"] = { first = 0x010A0, last = 0x010FF, otf="geor", description = "Georgian" },
+ ["georgianextended"] = { first = 0x01C90, last = 0x01CBF, description = "Georgian Extended" },
["georgiansupplement"] = { first = 0x02D00, last = 0x02D2F, otf="geor", description = "Georgian Supplement" },
["glagolitic"] = { first = 0x02C00, last = 0x02C5F, otf="glag", description = "Glagolitic" },
["glagoliticsupplement"] = { first = 0x1E000, last = 0x1E02F, description = "Glagolitic Supplement" },
@@ -322,6 +325,7 @@ local blocks = allocate {
["greekandcoptic"] = { first = 0x00370, last = 0x003FF, otf="grek", description = "Greek and Coptic" },
["greekextended"] = { first = 0x01F00, last = 0x01FFF, otf="grek", description = "Greek Extended" },
["gujarati"] = { first = 0x00A80, last = 0x00AFF, otf="gujr", description = "Gujarati" },
+ ["gunjalagondi"] = { first = 0x11D60, last = 0x11DAF, description = "Gunjala Gondi" },
["gurmukhi"] = { first = 0x00A00, last = 0x00A7F, otf="guru", description = "Gurmukhi" },
["halfwidthandfullwidthforms"] = { first = 0x0FF00, last = 0x0FFEF, description = "Halfwidth and Fullwidth Forms" },
["hangulcompatibilityjamo"] = { first = 0x03130, last = 0x0318F, otf="jamo", description = "Hangul Compatibility Jamo" },
@@ -329,6 +333,7 @@ local blocks = allocate {
["hanguljamoextendeda"] = { first = 0x0A960, last = 0x0A97F, description = "Hangul Jamo Extended-A" },
["hanguljamoextendedb"] = { first = 0x0D7B0, last = 0x0D7FF, description = "Hangul Jamo Extended-B" },
["hangulsyllables"] = { first = 0x0AC00, last = 0x0D7AF, otf="hang", description = "Hangul Syllables" },
+ ["hanifirohingya"] = { first = 0x10D00, last = 0x10D3F, description = "Hanifi Rohingya" },
["hanunoo"] = { first = 0x01720, last = 0x0173F, otf="hano", description = "Hanunoo" },
["hatran"] = { first = 0x108E0, last = 0x108FF, description = "Hatran" },
["hebrew"] = { first = 0x00590, last = 0x005FF, otf="hebr", description = "Hebrew" },
@@ -338,6 +343,7 @@ local blocks = allocate {
["ideographicdescriptioncharacters"] = { first = 0x02FF0, last = 0x02FFF, description = "Ideographic Description Characters" },
["ideographicsymbolsandpunctuation"] = { first = 0x16FE0, last = 0x16FFF, description = "Ideographic Symbols and Punctuation" },
["imperialaramaic"] = { first = 0x10840, last = 0x1085F, description = "Imperial Aramaic" },
+ ["indicsiyaqnumbers"] = { first = 0x1EC70, last = 0x1ECBF, description = "Indic Siyaq Numbers" },
["inscriptionalpahlavi"] = { first = 0x10B60, last = 0x10B7F, description = "Inscriptional Pahlavi" },
["inscriptionalparthian"] = { first = 0x10B40, last = 0x10B5F, description = "Inscriptional Parthian" },
["ipaextensions"] = { first = 0x00250, last = 0x002AF, description = "IPA Extensions" },
@@ -396,6 +402,7 @@ local blocks = allocate {
["lydian"] = { first = 0x10920, last = 0x1093F, description = "Lydian" },
["mahajani"] = { first = 0x11150, last = 0x1117F, description = "Mahajani" },
["mahjongtiles"] = { first = 0x1F000, last = 0x1F02F, description = "Mahjong Tiles" },
+ ["makasar"] = { first = 0x11EE0, last = 0x11EFF, description = "Makasar" },
["malayalam"] = { first = 0x00D00, last = 0x00D7F, otf="mlym", description = "Malayalam" },
["mandaic"] = { first = 0x00840, last = 0x0085F, otf="mand", description = "Mandaic" },
["manichaean"] = { first = 0x10AC0, last = 0x10AFF, description = "Manichaean" },
@@ -403,6 +410,8 @@ local blocks = allocate {
["masaramgondi"] = { first = 0x11D00, last = 0x11D5F, description = "Masaram Gondi" },
["mathematicalalphanumericsymbols"] = { first = 0x1D400, last = 0x1D7FF, math = true, description = "Mathematical Alphanumeric Symbols" },
["mathematicaloperators"] = { first = 0x02200, last = 0x022FF, math = true, description = "Mathematical Operators" },
+ ["mayannumerals"] = { first = 0x1D2E0, last = 0x1D2FF, description = "Mayan Numerals" },
+ ["medefaidrin"] = { first = 0x16E40, last = 0x16E9F, description = "Medefaidrin" },
["meeteimayek"] = { first = 0x0ABC0, last = 0x0ABFF, description = "Meetei Mayek" },
["meeteimayekextensions"] = { first = 0x0AAE0, last = 0x0AAFF, description = "Meetei Mayek Extensions" },
["mendekikakui"] = { first = 0x1E800, last = 0x1E8DF, description = "Mende Kikakui" },
@@ -438,6 +447,7 @@ local blocks = allocate {
["oldnortharabian"] = { first = 0x10A80, last = 0x10A9F, description = "Old North Arabian" },
["oldpermic"] = { first = 0x10350, last = 0x1037F, description = "Old Permic" },
["oldpersian"] = { first = 0x103A0, last = 0x103DF, otf="xpeo", description = "Old Persian" },
+ ["oldsogdian"] = { first = 0x10F00, last = 0x10F2F, description = "Old Sogdian" },
["oldsoutharabian"] = { first = 0x10A60, last = 0x10A7F, description = "Old South Arabian" },
["oldturkic"] = { first = 0x10C00, last = 0x10C4F, description = "Old Turkic" },
["opticalcharacterrecognition"] = { first = 0x02440, last = 0x0245F, description = "Optical Character Recognition" },
@@ -468,6 +478,7 @@ local blocks = allocate {
["sinhala"] = { first = 0x00D80, last = 0x00DFF, otf="sinh", description = "Sinhala" },
["sinhalaarchaicnumbers"] = { first = 0x111E0, last = 0x111FF, description = "Sinhala Archaic Numbers" },
["smallformvariants"] = { first = 0x0FE50, last = 0x0FE6F, description = "Small Form Variants" },
+ ["sogdian"] = { first = 0x10F30, last = 0x10F6F, description = "Sogdian" },
["sorasompeng"] = { first = 0x110D0, last = 0x110FF, description = "Sora Sompeng" },
["soyombo"] = { first = 0x11A50, last = 0x11AAF, description = "Soyombo" },
["spacingmodifierletters"] = { first = 0x002B0, last = 0x002FF, description = "Spacing Modifier Letters" },
@@ -606,7 +617,8 @@ characters.otfscripts = otfscripts
setmetatableindex(otfscripts,function(t,unicode)
for k, v in next, blocks do
- local first, last = v.first, v.last
+ local first = v.first
+ local last = v.last
if unicode >= first and unicode <= last then
local script = v.otf or "dflt"
for u=first,last do
@@ -631,25 +643,27 @@ function characters.getrange(name,expression) -- used in font fallback definitio
name = gsub(name,'"',"0x") -- goodie: tex hex notation
local start, stop
if expression then
- local first, rest = lpegmatch(splitter2,name)
- local range = rawget(blocks,lower(gsub(first,"[^a-zA-Z0-9]","")))
- if range then
- start = range.first
- stop = range.last
- local s = loadstring("return 0 " .. rest)
- if type(s) == "function" then
- local d = s()
- if type(d) == "number" then
- start = start + d
- stop = stop + d
- return start, stop, nil
+ local n = tonumber(name)
+ if n then
+ return n, n, nil
+ else
+ local first, rest = lpegmatch(splitter2,name)
+ local range = rawget(blocks,lower(gsub(first,"[^a-zA-Z0-9]","")))
+ if range then
+ local s = loadstring("return 0 " .. rest)
+ if type(s) == "function" then
+ local d = s()
+ if type(d) == "number" then
+ return range.first + d, range.last + d, nil
+ end
end
end
end
end
- start, stop = lpegmatch(splitter1,name)
+ local start, stop = lpegmatch(splitter1,name)
if start and stop then
- start, stop = tonumber(start,16) or tonumber(start), tonumber(stop,16) or tonumber(stop)
+ start = tonumber(start,16) or tonumber(start)
+ stop = tonumber(stop, 16) or tonumber(stop)
if start and stop then
return start, stop, nil
end
@@ -738,6 +752,10 @@ local is_punctuation = allocate ( tohash {
"pc","pd","ps","pe","pi","pf","po",
} )
+local is_symbol = allocate ( tohash {
+ "sm", "sc", "sk", "so",
+} )
+
-- to be redone: store checked characters
characters.is_character = is_character
@@ -746,6 +764,7 @@ characters.is_command = is_command
characters.is_spacing = is_spacing
characters.is_mark = is_mark
characters.is_punctuation = is_punctuation
+characters.is_symbol = is_symbol
local mti = function(t,k)
if type(k) == "number" then
@@ -1039,7 +1058,8 @@ setmetatableindex(specialchars, function(t,u)
local c = data[u]
local s = c and c.specials
if s then
- local tt, ttn = { }, 0
+ local tt = { }
+ local ttn = 0
for i=2,#s do
local si = s[i]
local c = data[si]
@@ -1265,9 +1285,11 @@ lpegpatterns.utf8lower = utf8lower -- string
lpegpatterns.utf8upper = utf8upper -- string
lpegpatterns.utf8shape = utf8shape -- string
-function characters.lower (str) return lpegmatch(utf8lower,str) end
-function characters.upper (str) return lpegmatch(utf8upper,str) end
-function characters.shaped(str) return lpegmatch(utf8shape,str) end
+function characters.lower (str) return str and lpegmatch(utf8lower,str) or "" end
+function characters.upper (str) return str and lpegmatch(utf8upper,str) or "" end
+function characters.shaped(str) return str and lpegmatch(utf8shape,str) or "" end
+
+lpeg.setutfcasers(characters.lower,characters.upper)
-- local str = [[
-- ÀÁÂÃÄÅàáâãäå àáâãäåàáâãäå ÀÁÂÃÄÅÀÁÂÃÄÅ AAAAAAaaaaaa
diff --git a/tex/context/base/mkiv/char-ini.mkiv b/tex/context/base/mkiv/char-ini.mkiv
index 9c41df673..0519aaf91 100644
--- a/tex/context/base/mkiv/char-ini.mkiv
+++ b/tex/context/base/mkiv/char-ini.mkiv
@@ -42,8 +42,8 @@
% use \normalUchar when possible .. the next one is nice for documents and it also accepts
% 0x prefixed numbers
-\def\utfchar #1{\clf_utfchar \numexpr#1\relax}
-\def\safechar#1{\clf_safechar\numexpr#1\relax}
+\def\utfchar #1{\clf_utfchar {#1}}
+\def\safechar#1{\clf_safechar{#1}}
\unexpanded\def\Ux #1{\Uchar\numexpr"#1\relax} % used in xml
\def\eUx#1{\Uchar\numexpr"#1\relax} % used in xml
@@ -66,6 +66,18 @@
\normalstartimath\char#1\normalstopimath
\fi\fi}
+\unexpanded\def\textormathchars#1%
+ {{\font_text_or_mathchars#1\relax}}
+
+\unexpanded\def\font_text_or_mathchars#1#2\relax
+ {\relax\ifmmode
+ #1#2%
+ \else\iffontchar\font`#1\relax
+ #1#2\relax
+ \else
+ \normalstartimath#1#2\normalstopimath
+ \fi\fi}
+
%D The codes are stored in the format, so we don't need to reinitialize
%D them (unless of course we have adapted the table). It is on the agenda
%D to do this with \type {tex.lccode} cum suis once they're available.
diff --git a/tex/context/base/mkiv/char-tex.lua b/tex/context/base/mkiv/char-tex.lua
index 065152881..bbaf11875 100644
--- a/tex/context/base/mkiv/char-tex.lua
+++ b/tex/context/base/mkiv/char-tex.lua
@@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['char-tex'] = {
local lpeg = lpeg
local tonumber, next, type = tonumber, next, type
-local format, find, gmatch = string.format, string.find, string.gmatch
+local format, find, gmatch, match = string.format, string.find, string.gmatch, string.match
local utfchar, utfbyte = utf.char, utf.byte
local concat, tohash = table.concat, table.tohash
local P, C, R, S, V, Cs, Cc = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.V, lpeg.Cs, lpeg.Cc
@@ -462,16 +462,24 @@ function commands.makeactive(n,name) -- not used
-- context("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name)
end
+local function to_number(s)
+ local n = tonumber(s)
+ if n then
+ return n
+ end
+ return tonumber(match(s,'^"(.*)$'),16) or 0
+end
+
implement {
name = "utfchar",
- actions = { utfchar, contextsprint },
- arguments = "integer"
+ actions = { to_number, utfchar, contextsprint },
+ arguments = "string"
}
implement {
name = "safechar",
- actions = { texcharacters.safechar, contextsprint },
- arguments = "integer"
+ actions = { to_number, texcharacters.safechar, contextsprint },
+ arguments = "string"
}
implement {
@@ -592,14 +600,17 @@ if not csletters then
end
--
if isletter then
- local lc, uc = chr.lccode, chr.uccode
+ local lc = chr.lccode
+ local uc = chr.uccode
if not lc then
- chr.lccode, lc = u, u
+ chr.lccode = u
+ lc = u
elseif type(lc) == "table" then
lc = u
end
if not uc then
- chr.uccode, uc = u, u
+ chr.uccode = u
+ uc = u
elseif type(uc) == "table" then
uc = u
end
@@ -623,12 +634,14 @@ if not csletters then
--
local lc, uc = chr.lccode, chr.uccode
if not lc then
- chr.lccode, lc = u, u
+ chr.lccode = u
+ lc = u
elseif type(lc) == "table" then
lc = u
end
if not uc then
- chr.uccode, uc = u, u
+ chr.uccode = u
+ uc = u
elseif type(uc) == "table" then
uc = u
end
diff --git a/tex/context/base/mkiv/char-utf.lua b/tex/context/base/mkiv/char-utf.lua
index 4dc7eba7a..110a4a48c 100644
--- a/tex/context/base/mkiv/char-utf.lua
+++ b/tex/context/base/mkiv/char-utf.lua
@@ -107,8 +107,10 @@ else
local function backtrack(v,last,target)
local vs = v.specials
if vs and #vs == 3 and vs[1] == "char" then
- local one, two = vs[2], vs[3]
- local first, second = utfchar(one), utfchar(two) .. last
+ local one = vs[2]
+ local two = vs[3]
+ local first = utfchar(one)
+ local second = utfchar(two) .. last
collapsed[first..second] = target
backtrack(data[one],second,target)
end
@@ -141,8 +143,11 @@ else
local size = #vs
if kind == "char" and size == 3 then -- what if more than 3
--
- local one, two = vs[2], vs[3]
- local first, second, combination = utfchar(one), utfchar(two), utfchar(unicode)
+ local one = vs[2]
+ local two = vs[3]
+ local first = utfchar(one)
+ local second = utfchar(two)
+ local combination = utfchar(unicode)
--
collapsed[first..second] = combination
backtrack(data[one],second,combination)
diff --git a/tex/context/base/mkiv/chem-str.lua b/tex/context/base/mkiv/chem-str.lua
index 7581a61d1..9f0738fc5 100644
--- a/tex/context/base/mkiv/chem-str.lua
+++ b/tex/context/base/mkiv/chem-str.lua
@@ -766,9 +766,6 @@ function chemistry.stop()
if trace_metapost then
report_chemistry("metapost code:\n%s", mpcode)
end
- if metapost.instance(chemistry.instance) then
- f_initialize = nil
- end
metapost.graphic {
instance = chemistry.instance,
format = chemistry.format,
@@ -776,7 +773,6 @@ function chemistry.stop()
data = mpcode,
definitions = f_initialize,
}
- t_initialize = ""
metacode = nil
end
end
diff --git a/tex/context/base/mkiv/chem-str.mkiv b/tex/context/base/mkiv/chem-str.mkiv
index 646cf13f1..71b104e47 100644
--- a/tex/context/base/mkiv/chem-str.mkiv
+++ b/tex/context/base/mkiv/chem-str.mkiv
@@ -650,18 +650,18 @@
\chem_formula_bot_nop
\fi\fi
\ifcsname\??chemicalsymbol d:\detokenize{#1}\endcsname
- \t_chem_mid\expandafter{\the\t_chem_mid\chemicalsymbol[d:#1]\aligntab}%
+ \toksapp\t_chem_mid{\chemicalsymbol[d:#1]\aligntab}%
\else
- \t_chem_mid\expandafter{\the\t_chem_mid\molecule{#1}\aligntab}%
+ \toksapp\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\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_nop {\toksapp\t_chem_top{\aligntab}}
+\def\chem_formula_bot_nop {\toksapp\t_chem_bot{\aligntab}}
+\def\chem_formula_top_yes#1{\toksapp\t_chem_top{\chem_formula_top_indeed{#1}\aligntab}\settrue\c_chem_has_top}
+\def\chem_formula_bot_yes#1{\toksapp\t_chem_bot{\chem_formula_bot_indeed{#1}\aligntab}\settrue\c_chem_has_bot}
\def\chem_formula_top_indeed#1{\strut#1}
\def\chem_formula_bot_indeed#1{\strut#1}
diff --git a/tex/context/base/mkiv/cldf-bas.lua b/tex/context/base/mkiv/cldf-bas.lua
index 070546637..f55132a06 100644
--- a/tex/context/base/mkiv/cldf-bas.lua
+++ b/tex/context/base/mkiv/cldf-bas.lua
@@ -22,27 +22,38 @@ if not modules then modules = { } end modules ['cldf-bas'] = {
-- flush(ctxcatcodes,"}")
-- end
-local tonumber = tonumber
-local type = type
-local format = string.format
-local utfchar = utf.char
-local concat = table.concat
+local tonumber = tonumber
+local type = type
+local format = string.format
+local utfchar = utf.char
+local concat = table.concat
-local context = context
-local ctxcore = context.core
-local variables = interfaces.variables
+local context = context
+local ctxcore = context.core
-local nodepool = nodes.pool
-local new_rule = nodepool.rule
-local new_glyph = nodepool.glyph
-local current_attr = nodes.current_attr
+local variables = interfaces.variables
-local current_font = font.current
-local texgetcount = tex.getcount
-local texsetcount = tex.setcount
+local ctx_flushnode = context.nuts.flush
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local nodepool = nuts.pool
+local new_rule = nodepool.rule
+local new_glyph = nodepool.glyph
+local new_latelua = nodepool.latelua
+
+local setattrlist = nuts.setattrlist
+
+local texgetcount = tex.getcount
+local texsetcount = tex.setcount
-- a set of basic fast ones
+function context.setfontid(n)
+ -- isn't there a setter?
+ context("\\setfontid%i\\relax",n)
+end
+
function context.char(k) -- used as escape too, so don't change to utf
if type(k) == "table" then
local n = #k
@@ -70,30 +81,35 @@ function context.utfchar(k)
end
end
-function context.rule(w,h,d,dir)
+function context.rule(w,h,d,direction)
local rule
if type(w) == "table" then
- rule = new_rule(w.width,w.height,w.depth,w.dir)
+ rule = new_rule(w.width,w.height,w.depth,w.direction)
else
- rule = new_rule(w,h,d,dir)
+ rule = new_rule(w,h,d,direction)
end
- rule.attr = current_attr()
- context(rule)
+ setattrlist(rule,true)
+ context(tonode(rule))
+ -- ctx_flushnode(tonode(rule))
end
function context.glyph(id,k)
if id then
if not k then
- id, k = current_font(), id
+ id, k = true, id
end
local glyph = new_glyph(id,k)
- glyph.attr = current_attr()
- context(glyph)
+ setattrlist(glyph,true)
+ context(tonode(glyph))
+ -- ctx_flushnode(tonode(glyph))
end
end
-local function ctx_par () context("\\par") end
-local function ctx_space() context("\\space") end
+-- local function ctx_par () context("\\par") end
+-- local function ctx_space() context("\\space") end
+
+local ctx_par = context.cs.par
+local ctx_space = context.cs.space
context.par = ctx_par
context.space = ctx_space
@@ -101,8 +117,11 @@ context.space = ctx_space
ctxcore.par = ctx_par
ctxcore.space = ctx_space
-local function ctx_bgroup() context("{") end
-local function ctx_egroup() context("}") end
+-- local function ctx_bgroup() context("{") end
+-- local function ctx_egroup() context("}") end
+
+local ctx_bgroup = context.cs.bgroup
+local ctx_egroup = context.cs.egroup
context.bgroup = ctx_bgroup
context.egroup = ctx_egroup
@@ -136,13 +155,21 @@ function ctxcore.flushboxregister(n)
context(type(n) == "number" and [[\box%s ]] or [[\box\%s]],n)
end
-function ctxcore.beginhbox() context([[\hbox{]]) end
-function ctxcore.beginvbox() context([[\vbox{]]) end
-function ctxcore.beginvtop() context([[\vtop{]]) end
+-- function ctxcore.beginhbox() context([[\hbox\bgroup]]) end
+-- function ctxcore.beginvbox() context([[\vbox\bgroup]]) end
+-- function ctxcore.beginvtop() context([[\vtop\bgroup]]) end
+
+local ctx_hbox = context.cs.hbox
+local ctx_vbox = context.cs.vbox
+local ctx_vtop = context.cs.vtop
-ctxcore.endhbox = ctx_egroup
-ctxcore.endvbox = ctx_egroup
-ctxcore.endvtop = ctx_egroup
+function ctxcore.beginhbox() ctx_hbox() ctx_bgroup() end
+function ctxcore.beginvbox() ctx_vbox() ctx_bgroup() end
+function ctxcore.beginvtop() ctx_vtop() ctx_bgroup() end
+
+ctxcore.endhbox = ctx_egroup -- \egroup
+ctxcore.endvbox = ctx_egroup -- \egroup
+ctxcore.endvtop = ctx_egroup -- \egroup
local function allocate(name,what,cmd)
local a = format("c_syst_last_allocated_%s",what)
@@ -165,3 +192,65 @@ context.registers = {
-- not really a register but kind of belongs here
newchar = function(name,u) context([[\chardef\%s=%s\relax]],name,u) end,
}
+
+do
+
+ if CONTEXTLMTXMODE > 1 then
+
+ function context.latelua(f)
+ -- table check moved elsewhere
+ local latelua = new_latelua(f)
+ setattrlist(latelua,true) -- will become an option
+ ctx_flushnode(latelua,true)
+ end
+
+ else
+
+ function context.latelua(f)
+ if type(f) == "table" then
+ local action = f.action
+ local specification = f.specification or f
+ f = function() action(specification) end
+ end
+ local latelua = new_latelua(f)
+ setattrlist(latelua,true) -- will become an option
+ ctx_flushnode(latelua,true)
+ end
+
+ end
+
+end
+-- yes or no
+
+do
+
+ local NC = ctxcore.NC
+ local BC = ctxcore.BC
+ local NR = ctxcore.NR
+
+ context.nc = setmetatable({ }, {
+ __call =
+ function(t,...)
+ NC()
+ return context(...)
+ end,
+ __index =
+ function(t,k)
+ NC()
+ return context[k]
+ end,
+ }
+ )
+
+ function context.bc(...)
+ BC()
+ return context(...)
+ end
+
+ function context.nr(...)
+ NC()
+ NR()
+ end
+
+end
+
diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua
index 8cd6408d3..9b1a4e368 100644
--- a/tex/context/base/mkiv/cldf-ini.lua
+++ b/tex/context/base/mkiv/cldf-ini.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['cldf-ini'] = {
license = "see context related readme files"
}
+-- todo: {token} -> 3 tokens
+
-- This started as an experiment: generating context code at the lua end. After all
-- it is surprisingly simple to implement due to metatables. I was wondering if
-- there was a more natural way to deal with commands at the lua end. Of course it's
@@ -29,7 +31,7 @@ if not modules then modules = { } end modules ['cldf-ini'] = {
-- todo : context("%bold{total: }%s",total)
-- todo : context.documentvariable("title")
--
--- during the crited project we ran into the situation that luajittex was 10-20 times
+-- During the crited project we ran into the situation that luajittex was 10-20 times
-- slower that luatex ... after 3 days of testing and probing we finally figured out that
-- the the differences between the lua and luajit hashers can lead to quite a slowdown
-- in some cases.
@@ -52,6 +54,11 @@ if not modules then modules = { } end modules ['cldf-ini'] = {
-- watching Trio Hiromi Uehara, Anthony Jackson & Simon Phillips (discovered via the
-- later on YT). Hopefully the video breaks made the following better in the end.
+-- This module is also a test bed for experimental features so the content changes over
+-- time (for the better or worse). There have been no fundamental changes for many years
+-- and performance has not changed much either.
+
+
local format, stripstring = string.format, string.strip
local next, type, tostring, tonumber, unpack, select, rawset = next, type, tostring, tonumber, unpack, select, rawset
local insert, remove, concat = table.insert, table.remove, table.concat
@@ -84,6 +91,13 @@ local texgetcount = tex.getcount
local isnode = node.is_node
local writenode = node.write
local copynodelist = node.copy_list
+local tonut = node.direct.todirect
+local tonode = node.direct.tonode
+
+local istoken = token.is_token
+local newtoken = token.new
+local createtoken = token.create
+local setluatoken = token.set_lua
local catcodenumbers = catcodes.numbers
@@ -104,16 +118,31 @@ local report_cld = logs.reporter("cld","stack")
local processlines = true -- experiments.register("context.processlines", function(v) processlines = v end)
+local tokenflushmode = true
+local nodeflushmode = true
+local scannerdefmode = true
+local maxflushnodeindex = 0x10FFFF - 1
+
+-- tokenflushmode = false
+-- scannerdefmode = false
+-- nodeflushmode = false
+
-- In earlier experiments a function tables was referred to as lua.calls and the
-- primitive \luafunctions was \luacall and we used our own implementation of
-- a function table (more indirectness).
+local trialtypesettingstate = createtoken("trialtypesettingstate").index
+
+function context.trialtypesetting()
+ return texgetcount(trialtypesettingstate) ~= 0
+end
+
local knownfunctions = lua.get_functions_table()
local showstackusage = false
trackers.register("context.stack",function(v) showstackusage = v end)
-local freed, nofused, noffreed = { }, 0, 0 -- maybe use the number of @@trialtypesetting
+local freed, nofused, noffreed = { }, 0, 0
local usedstack = function()
return nofused, noffreed
@@ -122,7 +151,7 @@ end
local flushfunction = function(slot,arg)
if arg() then
-- keep
- elseif texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private!
+ elseif texgetcount(trialtypesettingstate) == 0 then
noffreed = noffreed + 1
freed[noffreed] = slot
knownfunctions[slot] = false
@@ -147,7 +176,7 @@ local storefunction = function(arg)
end
local flushnode = function(slot,arg)
- if texgetcount("@@trialtypesetting") == 0 then -- @@trialtypesetting is private!
+ if texgetcount(trialtypesettingstate) == 0 then
writenode(arg)
noffreed = noffreed + 1
freed[noffreed] = slot
@@ -182,9 +211,13 @@ local f_resolve = nil
local p_resolve = ((1-lpegP("."))^1 / function(s) f_resolve = f_resolve[s] end * lpegP(".")^0)^1
local function resolvestoredfunction(str)
- f_resolve = global
- lpegmatch(p_resolve,str)
- return f_resolve
+ if type(str) == "string" then
+ f_resolve = global
+ lpegmatch(p_resolve,str)
+ return f_resolve
+ else
+ return str
+ end
end
local function expose(slot,f,...) -- so we can register yet undefined functions
@@ -246,17 +279,17 @@ local registerfunction = function(f,direct) -- either f=code or f=namespace,dire
func = resolvestoredfunction(f)
end
if type(func) ~= "function" then
- func = function() report_cld("invalid resolve %A",f) end
+ func = function() report_cld("invalid resolve %A, case %s",f,1) end
end
elseif type(f) == "string" then
func = loadstring(f)
if type(func) ~= "function" then
- func = function() report_cld("invalid code %A",f) end
+ func = function() report_cld("invalid code %A, case %s",f,2) end
end
elseif type(f) == "function" then
func = f
else
- func = function() report_cld("invalid function %A",f) end
+ func = function() report_cld("invalid function %A, case %s",f,3) end
end
knownfunctions[slot] = func
return slot
@@ -305,53 +338,52 @@ local storedscanners = interfaces.storedscanners
storage.register("interfaces/storedscanners", storedscanners, "interfaces.storedscanners")
local interfacescanners = setmetatablenewindex(function(t,k,v)
+ rawset(t,k,v)
if storedscanners[k] then
- -- report_cld("warning: scanner %a is already set",k)
+ -- report_cld("warning: scanner %a is already set (mode 1a)",k)
-- os.exit()
-- \scan_<k> is already in the format
-- report_cld("using interface scanner: %s",k)
+ elseif scannerdefmode then
+ -- report_cld("installing interface scanner: %s (mode 1b)",k)
+ -- local n = registerfunction(interfaces.scanners[k],true)
+ local n = registerfunction("interfaces.scanners."..k,true)
+ storedscanners[k] = n
+ local name = "clf_" .. k
+ setluatoken(name,n,"global") -- todo : protected and "protected" or ""
else
- -- todo: allocate slot here and pass it
+ -- report_cld("installing interface scanner: %s (mode 1c)",k)
storedscanners[k] = true
- -- report_cld("installing interface scanner: %s",k)
context("\\installctxscanner{clf_%s}{interfaces.scanners.%s}",k,k)
end
- rawset(t,k,v)
+ -- rawset(t,k,v)
end)
function interfaces.registerscanner(name,action,protected,public,call)
+ rawset(interfacescanners,name,action)
if storedscanners[name] then
- -- report_cld("warning: scanner %a is already set",k)
+ -- report_cld("warning: scanner %a is already set (mode 2a)",name)
-- os.exit()
-- \scan_<k> is already in the format
-- report_cld("using interface scanner: %s",k)
+ elseif scannerdefmode then
+ -- report_cld("installing interface scanner: %s (mode 2b)",name)
+ -- local n = registerfunction(action,true) -- todo
+ local n = registerfunction("interfaces.scanners."..name,true)
+ storedscanners[name] = n
+ local name = public and name or ("clf_" .. name)
+ setluatoken(name,n,"global",protected and "protected" or "")
else
storedscanners[name] = true
--- if protected then
--- -- report_cld("installing expandable interface scanner: %s",k)
--- if public then
--- context("\\installprotectedctxscanner{%s}{interfaces.scanners.%s}",name,name)
--- else
--- context("\\installprotectedctxscanner{clf_%s}{interfaces.scanners.%s}",name,name)
--- end
--- else
--- -- report_cld("installing protected interface scanner: %s",k)
--- if public then
--- context("\\installctxscanner{%s}{interfaces.scanners.%s}",name,name)
--- else
--- context("\\installctxscanner{clf_%s}{interfaces.scanners.%s}",name,name)
--- end
--- end
- -- report_cld("installing interface scanner: %s",k)
- context("\\install%sctxscanner%s{%s%s}{interfaces.scanners.%s}",
- protected and "protected" or "",
- call and "call" or "",
- public and "" or "clf_",
- name,
- name
- )
- end
- rawset(interfacescanners,name,action)
+ -- report_cld("installing interface scanner: %s (mode 2c)",name)
+ context("\\install%sctxscanner{%s%s}{interfaces.scanners.%s}",
+ protected and "protected" or "",
+ public and "" or "clf_",
+ name,
+ name
+ )
+ end
+ -- rawset(interfacescanners,name,action)
end
interfaces.scanners = storage.mark(interfacescanners)
@@ -379,7 +411,7 @@ end
local function dummy() end
-function commands.ctxresetter(name)
+function commands.ctxresetter(name) -- to be checked
return function()
if storedscanners[name] then
rawset(interfacescanners,name,dummy)
@@ -388,10 +420,6 @@ function commands.ctxresetter(name)
end
end
-function context.trialtypesetting()
- return texgetcount("@@trialtypesetting") ~= 0
-end
-
-- Should we keep the catcodes with the function?
local catcodestack = { }
@@ -673,6 +701,8 @@ local s_cldl_option_b = "[\\cldl"
local s_cldl_option_f = "[\\cldl" -- add space (not needed)
local s_cldl_option_e = "]"
local s_cldl_option_s = "\\cldl"
+----- s_cldl_option_d = "\\cldd"
+local s_cldl_option_d = s_cldl_option_s
local s_cldl_argument_b = "{\\cldl"
local s_cldl_argument_f = "{\\cldl "
local s_cldl_argument_e = "}"
@@ -683,14 +713,23 @@ local s_cldl_argument_e = "}"
-- local s_cldl_argument_b = "{"
-- local s_cldl_argument_f = "{ "
+local t_cldl_luafunction = createtoken("luafunctioncall")
+local lua_expandable_call_token_code = token.command_id and token.command_id("lua_expandable_call")
+
local function writer(parent,command,...) -- already optimized before call
- flush(currentcatcodes,command) -- todo: ctx|prt|texcatcodes
+
+ if type(command) == "string" then -- for now
+ flush(currentcatcodes,command) -- todo: ctx|prt|texcatcodes
+ else
+ flush(command) -- todo: ctx|prt|texcatcodes
+ end
+
local direct = false
-- local t = { ... }
-- for i=1,#t do
-- local ti = t[i]
for i=1,select("#",...) do
- local ti = (select(i,...))
+ local ti = select(i,...)
if direct then
local typ = type(ti)
if typ == "string" or typ == "number" then
@@ -703,6 +742,8 @@ local function writer(parent,command,...) -- already optimized before call
-- nothing
elseif ti == "" then
flush(currentcatcodes,"{}")
+ -- elseif ti == 1 then
+ -- flush(currentcatcodes,"{1}")
else
local typ = type(ti)
if typ == "string" then
@@ -719,7 +760,7 @@ local function writer(parent,command,...) -- already optimized before call
flush(currentcatcodes,"}")
end
elseif typ == "number" then
- -- numbers never have funny catcodes
+ -- numbers never have funny catcodesz
flush(currentcatcodes,"{",ti,"}")
elseif typ == "table" then
local tn = #ti
@@ -749,7 +790,16 @@ local function writer(parent,command,...) -- already optimized before call
elseif tn == 1 then -- some 20% faster than the next loop
local tj = ti[1]
if type(tj) == "function" then
- flush(currentcatcodes,s_cldl_option_b,storefunction(tj),s_cldl_option_e)
+ tj = storefunction(tj)
+ if tokenflushmode then
+ if newtoken then
+ flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_code),"]")
+ else
+ flush(currentcatcodes,"[",t_cldl_luafunction,tj,"]")
+ end
+ else
+ flush(currentcatcodes,s_cldl_option_b,tj,s_cldl_option_e)
+ end
else
flush(currentcatcodes,"[",tj,"]")
end
@@ -758,10 +808,15 @@ local function writer(parent,command,...) -- already optimized before call
for j=1,tn do
local tj = ti[j]
if type(tj) == "function" then
- if j == tn then
- flush(currentcatcodes,s_cldl_option_s,storefunction(tj),"]")
+ tj = storefunction(tj)
+ if tokenflushmode then
+ if newtoken then
+ flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_code),j == tn and "]" or ",")
+ else
+ flush(currentcatcodes,"[",t_cldl_luafunction,tj,j == tn and "]" or ",")
+ end
else
- flush(currentcatcodes,s_cldl_option_s,storefunction(tj),",")
+ flush(currentcatcodes,s_cldl_option_s,tj,j == tn and "]" or ",")
end
else
if j == tn then
@@ -774,7 +829,16 @@ local function writer(parent,command,...) -- already optimized before call
end
elseif typ == "function" then
-- todo: ctx|prt|texcatcodes
- flush(currentcatcodes,s_cldl_argument_f,storefunction(ti),s_cldl_argument_e)
+ ti = storefunction(ti)
+ if tokenflushmode then
+ if newtoken then
+ flush(currentcatcodes,"{",newtoken(ti,lua_expandable_call_token_code),"}")
+ else
+ flush(currentcatcodes,"{",t_cldl_luafunction,ti,"}")
+ end
+ else
+ flush(currentcatcodes,s_cldl_argument_f,ti,s_cldl_argument_e)
+ end
elseif typ == "boolean" then
if ti then
flushdirect(currentcatcodes,"\r")
@@ -783,62 +847,123 @@ local function writer(parent,command,...) -- already optimized before call
end
elseif typ == "thread" then
report_context("coroutines not supported as we cannot yield across boundaries")
- elseif isnode(ti) then -- slow
- flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e)
+ elseif isnode(ti) then -- slow | why {} here ?
+ if nodeflushmode then
+ local n = tonut(ti)
+ if n <= maxflushnodeindex then
+ flush(currentcatcodes,"{",ti,"}")
+ else
+ flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e)
+ end
+ else
+ flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e)
+ end
else
report_context("error: %a gets a weird argument %a",command,ti)
end
+-- else
+-- local n = isnode(ti)
+-- if n then
+-- if nodeflushmode and n <= maxflushnodeindex then
+-- flush(ti)
+-- else
+-- flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e)
+-- end
+-- else
+-- report_context("error: %a gets a weird argument %a",command,ti)
+-- end
+-- end
end
end
end
--- if performance really matters we can consider a compiler but it will never
--- pay off
-
--- local function prtwriter(command,...) -- already optimized before call
--- flush(prtcatcodes,command)
--- for i=1,select("#",...) do
--- local ti = (select(i,...))
--- if ti == nil then
--- -- nothing
--- elseif ti == "" then
--- flush(prtcatcodes,"{}")
--- else
--- local tp = type(ti)
--- if tp == "string" or tp == "number"then
--- flush(prtcatcodes,"{",ti,"}")
--- elseif tp == "function" then
--- flush(prtcatcodes,s_cldl_argument_f,storefunction(ti),s_cldl_argument_e)
--- elseif isnode(ti) then
--- flush(prtcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e)
+local core
+
+if tokenflushmode then -- combine them
+
+ local toks = tokens.cache
+
+ context.tokenizedcs = toks
+
+ core = setmetatableindex(function(parent,k)
+ local t
+ local f = function(first,...)
+ if not t then
+ t = toks[k]
+ end
+ if first == nil then
+ flush(t)
+ else
+ return writer(context,t,first,...)
+ end
+ end
+ parent[k] = f
+ return f
+ end)
+
+-- core = setmetatableindex(function(parent,k)
+-- local t
+-- local f = function(first,...)
+-- if not t then
+-- t = toks[k]
+-- end
+-- local f = function(first,...)
+-- if first == nil then
+-- flush(t)
-- else
--- report_context("fatal error: prt %a gets a weird argument %a",command,ti)
+-- return writer(context,t,first,...)
-- end
-- end
+-- parent[k] = f
+-- if first == nil then
+-- flush(t)
+-- else
+-- return writer(context,t,first,...)
+-- end
-- end
--- end
+-- parent[k] = f
+-- return f
+-- end)
+
+ core.cs = setmetatableindex(function(parent,k)
+ local t
+ local f = function()
+ if not t then
+ t = toks[k]
+ end
+ flush(t)
+ end
+ parent[k] = f
+ return f
+ end)
+
+else
+
+ context.tokenizedcs = false
+
+ core = setmetatableindex(function(parent,k)
+ local c = "\\" .. k
+ local f = function(first,...)
+ if first == nil then
+ flush(currentcatcodes,c)
+ else
+ return writer(context,c,first,...)
+ end
+ end
+ parent[k] = f
+ return f
+ end)
-local core = setmetatableindex(function(parent,k)
- local c = "\\" .. k -- tostring(k)
- local f = function(first,...)
- if first == nil then
+ core.cs = setmetatableindex(function(parent,k)
+ local c = "\\" .. k -- tostring(k)
+ local f = function()
flush(currentcatcodes,c)
- else
- return writer(context,c,first,...)
end
- end
- parent[k] = f
- return f
-end)
+ parent[k] = f
+ return f
+ end)
-core.cs = setmetatableindex(function(parent,k)
- local c = "\\" .. k -- tostring(k)
- local f = function()
- flush(currentcatcodes,c)
- end
- parent[k] = f
- return f
-end)
+end
local indexer = function(parent,k)
if type(k) == "string" then
@@ -933,8 +1058,16 @@ local caller = function(parent,f,a,...)
end
elseif typ == "function" then
-- ignored: a ...
- flush(currentcatcodes,"{\\cldl",storefunction(f),"}") -- todo: ctx|prt|texcatcodes
- -- flush(currentcatcodes,"{",storefunction(f),"}") -- todo: ctx|prt|texcatcodes
+ f = storefunction(f)
+ if tokenflushmode then
+ if newtoken then
+ flush(currentcatcodes,"{",newtoken(f,lua_expandable_call_token_code),"}")
+ else
+ flush(currentcatcodes,"{",t_cldl_luafunction,f,"}")
+ end
+ else
+ flush(currentcatcodes,s_cldl_argument_b,f,s_cldl_argument_e) -- todo: ctx|prt|texcatcodes
+ end
elseif typ == "boolean" then
if f then
if a ~= nil then
@@ -953,20 +1086,55 @@ local caller = function(parent,f,a,...)
elseif typ == "thread" then
report_context("coroutines not supported as we cannot yield across boundaries")
elseif isnode(f) then -- slow
- -- writenode(f)
- flush(currentcatcodes,"\\cldl",storenode(f)," ")
- -- flush(currentcatcodes,"",storenode(f)," ")
+ if nodeflushmode then
+ local n = tonut(f)
+ if n <= maxflushnodeindex then
+ flush(f)
+ else
+ flush(currentcatcodes,s_cldl_option_s,storenode(f)," ")
+ end
+ else
+ flush(currentcatcodes,s_cldl_option_s,storenode(f)," ")
+ end
else
report_context("error: %a gets a weird argument %a","context",f)
end
+-- else
+-- local n = isnode(f)
+-- if n then
+-- if nodeflushmode and n <= maxflushnodeindex then
+-- flush(f)
+-- else
+-- flush(currentcatcodes,s_cldl_option_s,storenode(f)," ")
+-- end
+-- else
+-- report_context("error: %a gets a weird argument %a","context",f)
+-- end
+-- end
end
end
-context.nodes = {
+context.nodes = { -- todo
store = storenode,
flush = function(n)
- flush(currentcatcodes,"\\cldl",storenode(n)," ")
- -- flush(currentcatcodes,"",storenode(n)," ")
+ if nodeflushmode and tonut(n) <= maxflushnodeindex then
+ flush(n)
+ else
+ flush(currentcatcodes,d and s_cldl_option_d or s_cldl_option_s,storenode(n)," ")
+ end
+ end,
+}
+
+context.nuts = { -- todo
+ store = function(n)
+ return storenode(tonut(n))
+ end,
+ flush = function(n,d)
+ if nodeflushmode and n <= maxflushnodeindex then
+ flush(tonode(n))
+ else
+ flush(currentcatcodes,d and s_cldl_option_d or s_cldl_option_s,storenode(tonode(n))," ")
+ end
end,
}
@@ -1012,8 +1180,8 @@ local nofflushes = 0
local tracingpermitted = true
local visualizer = lpeg.replacer {
- { "\n","<<newline>>" },
- { "\r","<<par>>" },
+ { "\n", "<<newline>>" },
+ { "\r", "<<par>>" },
}
statistics.register("traced context", function()
@@ -1026,13 +1194,48 @@ statistics.register("traced context", function()
end
end)
+local function userdata(argument)
+ if isnode(argument) then
+ return formatters["<< %s node %i>>"](nodes.nodecodes[argument.id],tonut(argument))
+ end
+ if istoken(argument) then
+ local csname = argument.csname
+ if csname then
+ -- return formatters["<<\\%s>>"](csname)
+ return formatters["\\%s"](csname)
+ end
+ local cmdname = argument.cmdname
+ if cmdname == "lua_expandable_call" or cmdname == "lua_call" then
+ return "<<function>>" -- argument.mode
+ end
+ return "<<token>>"
+ end
+ return "<<userdata>>"
+end
+
+
local tracedwriter = function(parent,...) -- also catcodes ?
nofwriters = nofwriters + 1
local savedflush = flush
local savedflushdirect = flushdirect -- unlikely to be used here
- local t, n = { "w : - : " }, 1
+ local t = { "w : - : " }
+ local n = 1
local traced = function(catcodes,...) -- todo: check for catcodes
- local s = concat({...})
+ local s = type(catcodes) == "number" and { ... } or { catcodes, ... }
+ for i=1,#s do
+ local argument = s[i]
+ local argtype = type(argument)
+ if argtype == "string" then
+ s[i] = lpegmatch(visualizer,argument)
+ elseif argtype == "number" then
+ s[i] = argument
+ elseif argtype == "userdata" then
+ s[i] = userdata(argument)
+ else
+ s[i] = formatters["<<%S>>"](argument)
+ end
+ end
+ s = concat(s)
s = lpegmatch(visualizer,s)
n = n + 1
t[n] = s
@@ -1060,9 +1263,10 @@ end
local traced = function(one,two,...)
if two ~= nil then
-- only catcodes if 'one' is number
- local catcodes = type(one) == "number" and one
+ local catcodes = type(one) == "number" and one
local arguments = catcodes and { two, ... } or { one, two, ... }
- local collapsed, c = { formatters["f : %s : "](catcodes or '-') }, 1
+ local collapsed = { formatters["f : %s : "](catcodes or '-') }
+ local c = 1
for i=1,#arguments do
local argument = arguments[i]
local argtype = type(argument)
@@ -1071,6 +1275,8 @@ local traced = function(one,two,...)
collapsed[c] = lpegmatch(visualizer,argument)
elseif argtype == "number" then
collapsed[c] = argument
+ elseif argtype == "userdata" then
+ collapsed[c] = userdata(argument)
else
collapsed[c] = formatters["<<%S>>"](argument)
end
@@ -1083,6 +1289,8 @@ local traced = function(one,two,...)
currenttrace(formatters["f : - : %s"](lpegmatch(visualizer,one)))
elseif argtype == "number" then
currenttrace(formatters["f : - : %s"](one))
+ elseif argtype == "userdata" then
+ currenttrace(formatters["F : - : %s"](userdata(one)))
else
currenttrace(formatters["f : - : <<%S>>"](one))
end
@@ -1175,24 +1383,21 @@ do
local sentinel = string.char(26) -- ASCII SUB character : endoffileasciicode : ignorecatcode
local level = 0
- local function collect(c,...) -- can be optimized
- -- snippets
- for i=1,select("#",...) do
+ local function collect(c,a,...) -- can be optimized
+ if type(c) == "userdata" then
nofcollected = nofcollected + 1
- collected[nofcollected] = (select(i,...))
+ -- collected[nofcollected] = userdata(c)
+ collected[nofcollected] = "\\" .. c.csname
+ end
+ if a then
+ for i=1,select("#",a,...) do
+ local c = select(i,a,...)
+ nofcollected = nofcollected + 1
+ collected[nofcollected] = type(c) == "userdata" and userdata(c) or c
+ end
end
end
- -- local function collectdirect(c,...) -- can be optimized
- -- -- lines
- -- for i=1,select("#",...) do
- -- n = n + 1
- -- t[n] = (select(i,...))
- -- n = n + 1
- -- t[n] = "\r"
- -- end
- -- end
-
local collectdirect = collect
local permitted = true
@@ -1224,34 +1429,39 @@ do
end
end
-end
-
---
+ local findtexfile = resolvers.findtexfile
+ local findfile = resolvers.findfile
-function context.runfile(filename)
- local foundname = resolvers.findtexfile(file.addsuffix(filename,"cld")) or ""
- if foundname ~= "" then
- local ok = dofile(foundname)
- if type(ok) == "function" then
- if trace_cld then
- report_context("begin of file %a (function call)",foundname)
- end
- ok()
- if trace_cld then
- report_context("end of file %a (function call)",foundname)
+ function context.runfile(filename)
+ local foundname = findtexfile(file.addsuffix(filename,"cld")) or ""
+ if foundname ~= "" then
+ local ok = dofile(foundname)
+ if type(ok) == "function" then
+ if trace_cld then
+ report_context("begin of file %a (function call)",foundname)
+ end
+ ok()
+ if trace_cld then
+ report_context("end of file %a (function call)",foundname)
+ end
+ elseif ok then
+ report_context("file %a is processed and returns true",foundname)
+ else
+ report_context("file %a is processed and returns nothing",foundname)
end
- elseif ok then
- report_context("file %a is processed and returns true",foundname)
else
- report_context("file %a is processed and returns nothing",foundname)
+ report_context("unknown file %a",filename)
end
- else
- report_context("unknown file %a",filename)
end
-end
-function context.loadfile(filename)
- context(stripstring(loaddata(resolvers.findfile(filename))))
+ function context.loadfile(filename)
+ context(stripstring(loaddata(findfile(filename))))
+ end
+
+ function context.loadviafile(filename)
+ viafile(stripstring(loaddata(findfile(filename))))
+ end
+
end
-- some functions
@@ -1270,7 +1480,7 @@ do
local function indexer(parent,k)
local f = function(...)
- local a = { ... }
+ local a = { ... } -- this also freezes ...
return function()
-- return context[k](unpack(a))
return core[k](unpack(a))
@@ -1295,46 +1505,48 @@ do
end
-do
-
- -- context.nested (todo: lines), creates strings
-
- local nested = { }
-
- local function indexer(parent,k) -- not ok when traced
- local f = function(...)
- local t, savedflush, n = { }, flush, 0
- flush = function(c,f,s,...) -- catcodes are ignored
- n = n + 1
- t[n] = s and concat{f,s,...} or f -- optimized for #args == 1
- end
- -- context[k](...)
- core[k](...)
- flush = savedflush
- return concat(t)
- end
- parent[k] = f
- return f
- end
-
- local function caller(parent,...)
- local t, savedflush, n = { }, flush, 0
- flush = function(c,f,s,...) -- catcodes are ignored
- n = n + 1
- t[n] = s and concat{f,s,...} or f -- optimized for #args == 1
- end
- -- context(...)
- defaultcaller(context,...)
- flush = savedflush
- return concat(t)
- end
-
- setmetatableindex(nested,indexer)
- setmetatablecall (nested,caller)
-
- context.nested = nested
+-- do
+--
+-- -- context.nested (todo: lines), creates strings
+--
+-- local nested = { }
+--
+-- local function indexer(parent,k) -- not ok when traced
+-- local f = function(...)
+-- local t, savedflush, n = { }, flush, 0
+-- flush = function(c,f,s,...) -- catcodes are ignored
+-- n = n + 1
+-- t[n] = s and concat{f,s,...} or f -- optimized for #args == 1
+-- end
+-- -- context[k](...)
+-- core[k](...)
+-- flush = savedflush
+-- return concat(t)
+-- end
+-- parent[k] = f
+-- return f
+-- end
+--
+-- local function caller(parent,...)
+-- local t, savedflush, n = { }, flush, 0
+-- flush = function(c,f,s,...) -- catcodes are ignored
+-- n = n + 1
+-- t[n] = s and concat{f,s,...} or f -- optimized for #args == 1
+-- end
+-- -- context(...)
+-- defaultcaller(context,...)
+-- flush = savedflush
+-- return concat(t)
+-- end
+--
+-- setmetatableindex(nested,indexer)
+-- setmetatablecall (nested,caller)
+--
+-- context.nested = nested
+--
+-- end
-end
+context.nested = context.delayed
-- verbatim
@@ -1360,14 +1572,22 @@ function context.newindexer(catcodes,cmdcodes)
contentcatcodes = savedcatcodes
end
- handler.cs = setmetatableindex(function(parent,k)
- local c = "\\" .. k -- tostring(k)
- local f = function()
- flush(cmdcodes,c)
- end
- parent[k] = f
- return f
- end)
+ if tokenflushmode then
+
+ handler.cs = core.cs
+
+ else
+
+ handler.cs = setmetatableindex(function(parent,k)
+ local c = "\\" .. k -- tostring(k)
+ local f = function()
+ flush(cmdcodes,c)
+ end
+ parent[k] = f
+ return f
+ end)
+
+ end
setmetatableindex(handler,indexer)
setmetatablecall (handler,caller)
@@ -1420,21 +1640,51 @@ do
end
end
- local function indexer(parent,k)
- if type(k) == "string" then
- local c = "\\" .. k
- local f = function(first,...)
- if first == nil then
- flush(currentcatcodes,c)
- else
- return formattedflush(parent,c,first,...)
+ local indexer
+
+ if tokenflushmode then -- combine them
+
+ local toks = tokens.cache
+
+ indexer = function(parent,k)
+ if type(k) == "string" then
+ local t
+ local f = function(first,...)
+ if not t then
+ t = toks[k]
+ end
+ if first == nil then
+ flush(t)
+ else
+ return formattedflush(parent,t,first,...)
+ end
+ end
+ parent[k] = f
+ return f
+ else
+ return context -- catch
+ end
+ end
+
+ else
+
+ indexer = function(parent,k)
+ if type(k) == "string" then
+ local c = "\\" .. k
+ local f = function(first,...)
+ if first == nil then
+ flush(currentcatcodes,c)
+ else
+ return formattedflush(parent,c,first,...)
+ end
end
+ parent[k] = f
+ return f
+ else
+ return context -- catch
end
- parent[k] = f
- return f
- else
- return context -- catch
end
+
end
-- formatted([catcodes,]format[,...])
diff --git a/tex/context/base/mkiv/cldf-ini.mkiv b/tex/context/base/mkiv/cldf-ini.mkiv
index 27ce42aa2..29fb15d68 100644
--- a/tex/context/base/mkiv/cldf-ini.mkiv
+++ b/tex/context/base/mkiv/cldf-ini.mkiv
@@ -13,6 +13,8 @@
\writestatus{loading}{ConTeXt Lua Documents / Initialization}
+\newcount\trialtypesettingstate % gets aliased at the Lua end
+
\registerctxluafile{cldf-ini}{}
%D With each new update of \MKIV\ we can join Within Temptation in
@@ -41,14 +43,16 @@
% \fi
\let\cldl\luafunction
+\let\cldd\lateluafunction
% \catcode`=\activecatcode \let\luafunction % saves 10% on the call
-% \catcodetable\ctxcatcodes \catcode`^=\superscriptcatcode\catcode1=\activecatcode \global\let^^A=\cldf
-% \catcodetable\ctxcatcodes \catcode`^=\superscriptcatcode\catcode2=\activecatcode \global\let^^B=\cldn
+% \catcodetable\ctxcatcodes \catcode`^=\superscriptcatcode\catcode1=\activecatcode \glet^^A=\cldf
+% \catcodetable\ctxcatcodes \catcode`^=\superscriptcatcode\catcode2=\activecatcode \glet^^B=\cldn
\normalprotected\def\cldprocessfile#1{\directlua{context.runfile("#1")}}
\def\cldloadfile #1{\directlua{context.loadfile("#1")}}
+ \def\cldloadviafile#1{\directlua{context.loadviafile("#1")}}
\def\cldcontext #1{\directlua{context(#1)}}
\def\cldcommand #1{\directlua{context.#1}}
% \def\cldverbatim #1{\directlua{context.verbatim.#1}} % maybe make verbatim global
diff --git a/tex/context/base/mkiv/cldf-int.lua b/tex/context/base/mkiv/cldf-int.lua
index a97eadf35..52cfea8d0 100644
--- a/tex/context/base/mkiv/cldf-int.lua
+++ b/tex/context/base/mkiv/cldf-int.lua
@@ -88,9 +88,10 @@ function interfaces.definecommand(name,specification) -- name is optional
else
-- we could flush immediate but tracing is bad then
stack[name] = { }
- local opt, done = 0, false
+ local opt = 0
+ local done = false
local snippets = { } -- we can reuse it
- local mkivdo = "\\mkivdo" .. name -- maybe clddo
+ local mkivdo = "\\mkivdo" .. name -- maybe clddo
snippets[#snippets+1] = "\\def"
snippets[#snippets+1] = mkivdo
for i=1,na do
diff --git a/tex/context/base/mkiv/cldf-scn.lua b/tex/context/base/mkiv/cldf-scn.lua
index ccf1f01c6..d0b16e034 100644
--- a/tex/context/base/mkiv/cldf-scn.lua
+++ b/tex/context/base/mkiv/cldf-scn.lua
@@ -25,6 +25,7 @@ local scanners = interfaces.scanners
local register = interfaces.registerscanner
local compile = tokens.compile or function() end
+local presets = tokens.presets
local dummy = function() end
@@ -47,6 +48,10 @@ function interfaces.implement(specification)
if name == "" then
name = nil
end
+ local p = arguments and presets[arguments]
+ if p then
+ arguments = p
+ end
local scanner
local resetter = onlyonce and name and commands.ctxresetter(name)
if resetter then
@@ -72,7 +77,7 @@ function interfaces.implement(specification)
if scanners[name] and not specification.overload then
report("warning: 'scanners.%s' is redefined",name)
end
--- scanners[name] = scanner
+ -- scanners[name] = scanner -- we now use:
register(name,scanner,specification.protected,specification.public,specification.call)
if private then
return
diff --git a/tex/context/base/mkiv/cldf-ver.lua b/tex/context/base/mkiv/cldf-ver.lua
index 3710b2415..7a1c81301 100644
--- a/tex/context/base/mkiv/cldf-ver.lua
+++ b/tex/context/base/mkiv/cldf-ver.lua
@@ -13,32 +13,69 @@ if not modules then modules = { } end modules ['cldf-ver'] = {
local concat, tohandle = table.concat, table.tohandle
local splitlines, strip = string.splitlines, string.strip
local tostring, type = tostring, type
+local assignbuffer = buffers.assign
local context = context
-local function flush(...)
- context(concat{...,"\r"}) -- was \n
+context.tobuffer = assignbuffer -- (name,str,catcodes)
+
+function context.tolines(str,strip)
+ local lines = type(str) == "string" and splitlines(str) or str
+ for i=1,#lines do
+ if strip then
+ context(strip(lines[i]) .. " ")
+ else
+ context(lines[i] .. " ")
+ end
+ end
end
-local function t_tocontext(...)
- context.starttyping { "typing" } -- else [1] is intercepted
- context.pushcatcodes("verbatim")
- tohandle(flush,...) -- ok?
- context.stoptyping()
- context.popcatcodes()
+-- local function flush(...)
+-- context(concat { ..., "\r" }) -- was \n
+-- end
+--
+-- somehow this doesn't work any longer .. i need to figure out why
+--
+-- local function t_tocontext(t)
+-- context.starttyping { "typing" } -- else [1] is intercepted
+-- context.pushcatcodes("verbatim")
+-- -- tohandle(flush,...)
+-- context(table.serialize(t))
+-- context.stoptyping()
+-- context.popcatcodes()
+-- end
+--
+-- local function s_tocontext(first,second,...) -- we need to catch {\}
+-- context.type()
+-- context("{")
+-- context.pushcatcodes("verbatim")
+-- if second then
+-- context(concat({ first, second, ... }, " "))
+-- else
+-- context(first) -- no need to waste a { }
+-- end
+-- context.popcatcodes()
+-- context("}")
+-- end
+
+local t_buffer = { "t_o_c_o_n_t_e_x_t" }
+local t_typing = { "typing" }
+local t_type = { "type" }
+
+local function flush(s,inline)
+ assignbuffer("t_o_c_o_n_t_e_x_t",s)
+ context[inline and "typeinlinebuffer" or "typebuffer"](t_buffer)
+ context.resetbuffer(t_buffer)
end
-local function s_tocontext(first,...) -- we need to catch {\}
- context.type()
- context("{")
- context.pushcatcodes("verbatim")
- if first then
- context(first) -- no need to waste a { }
- else
- context(concat({first,...}," "))
- end
- context.popcatcodes()
- context("}")
+local function t_tocontext(t)
+ local s = table.serialize(t)
+ context(function() flush(s,false) end)
+end
+
+local function s_tocontext(first,second,...) -- we need to catch {\}
+ local s = second and concat({ first, second, ... }, " ") or first
+ context(function() flush(s,true) end)
end
local function b_tocontext(b)
@@ -74,15 +111,3 @@ end)
context.tocontext = tocontext
-context.tobuffer = buffers.assign -- (name,str,catcodes)
-
-function context.tolines(str,strip)
- local lines = type(str) == "string" and splitlines(str) or str
- for i=1,#lines do
- if strip then
- context(strip(lines[i]) .. " ")
- else
- context(lines[i] .. " ")
- end
- end
-end
diff --git a/tex/context/base/mkiv/colo-imp-crayola.mkiv b/tex/context/base/mkiv/colo-imp-crayola.mkiv
index dbae02d5a..ae955ec1c 100644
--- a/tex/context/base/mkiv/colo-imp-crayola.mkiv
+++ b/tex/context/base/mkiv/colo-imp-crayola.mkiv
@@ -1,9 +1,9 @@
%D \module
-%D [ file=colo-imp-crayola
-%D version=2016.03.21,
-%D title=\CONTEXT\ Color Macros,
-%D subtitle=Crayola,
-%D author=Alan Braslau]
+%D [ file=colo-imp-crayola
+%D version=2016.03.21,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Crayola,
+%D author=Alan Braslau]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA, See mreadme.pdf for
diff --git a/tex/context/base/mkiv/colo-imp-svg.mkiv b/tex/context/base/mkiv/colo-imp-svg.mkiv
new file mode 100644
index 000000000..f39adaa98
--- /dev/null
+++ b/tex/context/base/mkiv/colo-imp-svg.mkiv
@@ -0,0 +1,164 @@
+%D \module
+%D [ file=colo-imp-svg,
+%D version=2018.09.17,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=SVG]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA, See mreadme.pdf for
+%C details.
+
+%D This module was prepared by an user who wants to stay anonymous and is
+%D derived from \url {http://www.december.com/html/spec/colorsvghex.html}.
+
+\startprotectedcolors
+
+\definecolor [black] [h=000000]
+\definecolor [navy] [h=000080]
+\definecolor [darkblue] [h=00008B]
+\definecolor [mediumblue] [h=0000CD]
+\definecolor [blue] [h=0000FF]
+\definecolor [darkgreen] [h=006400]
+\definecolor [green] [h=008000]
+\definecolor [teal] [h=008080]
+\definecolor [darkcyan] [h=008B8B]
+\definecolor [deepskyblue] [h=00BFFF]
+\definecolor [darkturquoise] [h=00CED1]
+\definecolor [mediumspringgreen] [h=00FA9A]
+\definecolor [lime] [h=00FF00]
+\definecolor [springgreen] [h=00FF7F]
+\definecolor [cyan] [h=00FFFF]
+\definecolor [aqua] [h=00FFFF]
+\definecolor [midnightblue] [h=191970]
+\definecolor [dodgerblue] [h=1E90FF]
+\definecolor [lightseagreen] [h=20B2AA]
+\definecolor [forestgreen] [h=228B22]
+\definecolor [seagreen] [h=2E8B57]
+\definecolor [darkslategray] [h=2F4F4F]
+\definecolor [darkslategrey] [h=2F4F4F]
+\definecolor [limegreen] [h=32CD32]
+\definecolor [mediumseagreen] [h=3CB371]
+\definecolor [turquoise] [h=40E0D0]
+\definecolor [royalblue] [h=4169E1]
+\definecolor [steelblue] [h=4682B4]
+\definecolor [darkslateblue] [h=483D8B]
+\definecolor [mediumturquoise] [h=48D1CC]
+\definecolor [indigo] [h=4B0082]
+\definecolor [darkolivegreen] [h=556B2F]
+\definecolor [cadetblue] [h=5F9EA0]
+\definecolor [cornflowerblue] [h=6495ED]
+\definecolor [mediumaquamarine] [h=66CDAA]
+\definecolor [dimgrey] [h=696969]
+\definecolor [dimgray] [h=696969]
+\definecolor [slateblue] [h=6A5ACD]
+\definecolor [olivedrab] [h=6B8E23]
+\definecolor [slategrey] [h=708090]
+\definecolor [slategray] [h=708090]
+\definecolor [lightslategray] [h=778899]
+\definecolor [lightslategrey] [h=778899]
+\definecolor [mediumslateblue] [h=7B68EE]
+\definecolor [lawngreen] [h=7CFC00]
+\definecolor [chartreuse] [h=7FFF00]
+\definecolor [aquamarine] [h=7FFFD4]
+\definecolor [maroon] [h=800000]
+\definecolor [purple] [h=800080]
+\definecolor [olive] [h=808000]
+\definecolor [gray] [h=808080]
+\definecolor [grey] [h=808080]
+\definecolor [skyblue] [h=87CEEB]
+\definecolor [lightskyblue] [h=87CEFA]
+\definecolor [blueviolet] [h=8A2BE2]
+\definecolor [darkred] [h=8B0000]
+\definecolor [darkmagenta] [h=8B008B]
+\definecolor [saddlebrown] [h=8B4513]
+\definecolor [darkseagreen] [h=8FBC8F]
+\definecolor [lightgreen] [h=90EE90]
+\definecolor [mediumpurple] [h=9370DB]
+\definecolor [darkviolet] [h=9400D3]
+\definecolor [palegreen] [h=98FB98]
+\definecolor [darkorchid] [h=9932CC]
+\definecolor [yellowgreen] [h=9ACD32]
+\definecolor [sienna] [h=A0522D]
+\definecolor [brown] [h=A52A2A]
+\definecolor [darkgray] [h=A9A9A9]
+\definecolor [darkgrey] [h=A9A9A9]
+\definecolor [lightblue] [h=ADD8E6]
+\definecolor [greenyellow] [h=ADFF2F]
+\definecolor [paleturquoise] [h=AFEEEE]
+\definecolor [lightsteelblue] [h=B0C4DE]
+\definecolor [powderblue] [h=B0E0E6]
+\definecolor [firebrick] [h=B22222]
+\definecolor [darkgoldenrod] [h=B8860B]
+\definecolor [mediumorchid] [h=BA55D3]
+\definecolor [rosybrown] [h=BC8F8F]
+\definecolor [darkkhaki] [h=BDB76B]
+\definecolor [silver] [h=C0C0C0]
+\definecolor [mediumvioletred] [h=C71585]
+\definecolor [indianred] [h=CD5C5C]
+\definecolor [peru] [h=CD853F]
+\definecolor [chocolate] [h=D2691E]
+\definecolor [tan] [h=D2B48C]
+\definecolor [lightgray] [h=D3D3D3]
+\definecolor [lightgrey] [h=D3D3D3]
+\definecolor [thistle] [h=D8BFD8]
+\definecolor [orchid] [h=DA70D6]
+\definecolor [goldenrod] [h=DAA520]
+\definecolor [palevioletred] [h=DB7093]
+\definecolor [crimson] [h=DC143C]
+\definecolor [gainsboro] [h=DCDCDC]
+\definecolor [plum] [h=DDA0DD]
+\definecolor [burlywood] [h=DEB887]
+\definecolor [lightcyan] [h=E0FFFF]
+\definecolor [lavender] [h=E6E6FA]
+\definecolor [darksalmon] [h=E9967A]
+\definecolor [violet] [h=EE82EE]
+\definecolor [palegoldenrod] [h=EEE8AA]
+\definecolor [lightcoral] [h=F08080]
+\definecolor [khaki] [h=F0E68C]
+\definecolor [aliceblue] [h=F0F8FF]
+\definecolor [honeydew] [h=F0FFF0]
+\definecolor [azure] [h=F0FFFF]
+\definecolor [sandybrown] [h=F4A460]
+\definecolor [wheat] [h=F5DEB3]
+\definecolor [beige] [h=F5F5DC]
+\definecolor [whitesmoke] [h=F5F5F5]
+\definecolor [mintcream] [h=F5FFFA]
+\definecolor [ghostwhite] [h=F8F8FF]
+\definecolor [salmon] [h=FA8072]
+\definecolor [antiquewhite] [h=FAEBD7]
+\definecolor [linen] [h=FAF0E6]
+\definecolor [lightgoldenrodyellow] [h=FAFAD2]
+\definecolor [oldlace] [h=FDF5E6]
+\definecolor [red] [h=FF0000]
+\definecolor [fuchsia] [h=FF00FF]
+\definecolor [magenta] [h=FF00FF]
+\definecolor [deeppink] [h=FF1493]
+\definecolor [orangered] [h=FF4500]
+\definecolor [tomato] [h=FF6347]
+\definecolor [hotpink] [h=FF69B4]
+\definecolor [coral] [h=FF7F50]
+\definecolor [darkorange] [h=FF8C00]
+\definecolor [lightsalmon] [h=FFA07A]
+\definecolor [orange] [h=FFA500]
+\definecolor [lightpink] [h=FFB6C1]
+\definecolor [pink] [h=FFC0CB]
+\definecolor [gold] [h=FFD700]
+\definecolor [peachpuff] [h=FFDAB9]
+\definecolor [navajowhite] [h=FFDEAD]
+\definecolor [moccasin] [h=FFE4B5]
+\definecolor [bisque] [h=FFE4C4]
+\definecolor [mistyrose] [h=FFE4E1]
+\definecolor [blanchedalmond] [h=FFEBCD]
+\definecolor [papayawhip] [h=FFEFD5]
+\definecolor [lavenderblush] [h=FFF0F5]
+\definecolor [seashell] [h=FFF5EE]
+\definecolor [cornsilk] [h=FFF8DC]
+\definecolor [lemonchiffon] [h=FFFACD]
+\definecolor [floralwhite] [h=FFFAF0]
+\definecolor [snow] [h=FFFAFA]
+\definecolor [yellow] [h=FFFF00]
+\definecolor [lightyellow] [h=FFFFE0]
+\definecolor [ivory] [h=FFFFF0]
+\definecolor [white] [h=FFFFFF]
+
+\stopprotectedcolors
diff --git a/tex/context/base/mkiv/colo-ini.lua b/tex/context/base/mkiv/colo-ini.lua
index 921612b0f..3c8d23abc 100644
--- a/tex/context/base/mkiv/colo-ini.lua
+++ b/tex/context/base/mkiv/colo-ini.lua
@@ -43,6 +43,7 @@ local texsetattribute = tex.setattribute
local texgetattribute = tex.getattribute
local texgetcount = tex.getcount
local texgettoks = tex.gettoks
+local texgetmacro = tokens.getters.macro
local a_color = attributes.private('color')
local a_transparency = attributes.private('transparency')
@@ -273,7 +274,9 @@ local function forcedmodel(model) -- delayed till the backend but mp directly
return 2
end
elseif model == 5 then -- spot
- if cmyk_okay then
+ if spot_okay then
+ return 5
+ elseif cmyk_okay then
return 4
elseif rgb_okay then
return 3
@@ -309,7 +312,8 @@ local function definetransparency(name,n,global)
end
local settings = settings_to_hash_strict(n)
if settings then
- local a, t = settings.a, settings.t
+ local a = settings.a
+ local t = settings.t
if a and t then
definetransparent(name, transparencies.register(name,transparent[a] or tonumber(a) or 1,tonumber(t) or 1), global)
else
@@ -440,16 +444,23 @@ local function defineprocesscolor(name,str,global,freeze) -- still inconsistent
else
local settings = settings_to_hash_strict(str)
if settings then
- local r, g, b = settings.r, settings.g, settings.b
+ local r = settings.r
+ local g = settings.g
+ local b = settings.b
if r or g or b then
-- we can consider a combined rgb cmyk s definition
definecolor(name, register_color(name,'rgb', tonumber(r) or 0, tonumber(g) or 0, tonumber(b) or 0), global)
else
- local c, m, y, k = settings.c, settings.m, settings.y, settings.k
+ local c = settings.c
+ local m = settings.m
+ local y = settings.y
+ local k = settings.k
if c or m or y or k then
definecolor(name, register_color(name,'cmyk',tonumber(c) or 0, tonumber(m) or 0, tonumber(y) or 0, tonumber(k) or 0), global)
else
- local h, s, v = settings.h, settings.s, settings.v
+ local h = settings.h
+ local s = settings.s
+ local v = settings.v
if v then
r, g, b = colors.hsvtorgb(tonumber(h) or 0, tonumber(s) or 1, tonumber(v) or 1) -- maybe later native
definecolor(name, register_color(name,'rgb',r,g,b), global)
@@ -468,7 +479,8 @@ local function defineprocesscolor(name,str,global,freeze) -- still inconsistent
end
end
end
- local a, t = settings.a, settings.t
+ local a = settings.a
+ local t = settings.t
if a and t then
definetransparent(name, transparencies.register(name,transparent[a] or tonumber(a) or 1,tonumber(t) or 1), global)
elseif colors.couple then
@@ -520,7 +532,8 @@ local function definespotcolor(name,parent,str,global)
do_registerspotcolor(parent,cp,t.e,1,"",tp) -- p not really needed, only diagnostics
if name and name ~= "" then
definecolor(name,register_color(name,'spot',parent,1,"",tp),true)
- local ta, tt = t.a, t.t
+ local ta = t.a
+ local tt = t.t
if ta and tt then
definetransparent(name, transparencies.register(name,transparent[ta] or tonumber(ta) or 1,tonumber(tt) or 1), global)
elseif colors.couple then
@@ -564,7 +577,7 @@ local function f(i,colors,fraction)
return otf
end
-local function definemixcolor(makename,name,fractions,cs,global,freeze)
+local function definemixcolor(makecolor,name,fractions,cs,global,freeze)
local values = { }
for i=1,#cs do -- do fraction in here
local v = colorvalues[cs[i]]
@@ -592,12 +605,15 @@ local function definemixcolor(makename,name,fractions,cs,global,freeze)
end
definecolor(name,ca,global,freeze)
else
- report_colors("invalid specification of components for color %a",makename)
+ report_colors("invalid specification of components for color %a",makecolor)
end
end
local function definemultitonecolor(name,multispec,colorspec,selfspec)
- local dd, pp, nn, max = { }, { }, { }, 0
+ local dd = { }
+ local pp = { }
+ local nn = { }
+ local max = 0
for k,v in gmatch(multispec,"([^=,]+)=([^%,]*)") do -- use settings_to_array
max = max + 1
dd[max] = k
@@ -608,12 +624,12 @@ local function definemultitonecolor(name,multispec,colorspec,selfspec)
nn = concat(nn,'_')
local parent = gsub(lower(nn),"[^%d%a%.]+","_")
if not colorspec or colorspec == "" then
+ -- this can happens when we come from metapost
local cc = { }
for i=1,max do
--- cc[i] = l_color[dd[i]]
cc[i] = resolvedname(dd[i])
end
- definemixcolor(name,parent,pp,cc,global,freeze) -- can become local
+ definemixcolor(name,parent,pp,cc,true,true)
else
if selfspec ~= "" then
colorspec = colorspec .. "," .. selfspec
@@ -645,24 +661,29 @@ colors.definemultitonecolor = definemultitonecolor
-- that we cannot cast .. so we really need to use (s,s,s) for gray in order
-- to be able to map onto 'color'
-local function mpcolor(model,ca,ta,default)
+local function mpcolor(model,ca,ta,default,name)
local cv = colorvalues[ca]
if cv then
local tv = transparencyvalues[ta]
+ -- maybe move the 5 logic into the forcedmodel call
+ local cm = cv[1]
if model == 1 then
- model = cv[1]
+ model = cm
end
model = forcedmodel(model)
+ if cm == 5 and model == 4 then
+ model = 5 -- a cheat but ok as spot colors have a representation
+ end
if tv then
if model == 2 then
return formatters["transparent(%s,%s,(%s,%s,%s))"](tv[1],tv[2],cv[3],cv[4],cv[5])
elseif model == 3 then
return formatters["transparent(%s,%s,(%s,%s,%s))"](tv[1],tv[2],cv[3],cv[4],cv[5])
elseif model == 4 then
- return formatters["transparent(%s,%s,cmyk(%s,%s,%s,%s))"](tv[1],tv[2],cv[6],cv[7],cv[8],cv[9])
+ return formatters["transparent(%s,%s,(%s,%s,%s,%s))"](tv[1],tv[2],cv[6],cv[7],cv[8],cv[9])
elseif model == 5 then
-- return formatters['transparent(%s,%s,multitonecolor("%s",%s,"%s","%s"))'](tv[1],tv[2],cv[10],cv[11],cv[12],cv[13])
- return formatters['transparent(%s,%s,namedcolor("%s"))'](tv[1],tv[2],cv[10])
+ return formatters['transparent(%s,%s,namedcolor("%s"))'](tv[1],tv[2],name or cv[10])
else -- see ** in meta-ini.mkiv: return formatters["transparent(%s,%s,(%s))"](tv[1],tv[2],cv[2])
return formatters["transparent(%s,%s,(%s,%s,%s))"](tv[1],tv[2],cv[3],cv[4],cv[5])
end
@@ -672,10 +693,9 @@ local function mpcolor(model,ca,ta,default)
elseif model == 3 then
return formatters["(%s,%s,%s)"](cv[3],cv[4],cv[5])
elseif model == 4 then
- return formatters["cmyk(%s,%s,%s,%s)"](cv[6],cv[7],cv[8],cv[9])
+ return formatters["(%s,%s,%s,%s)"](cv[6],cv[7],cv[8],cv[9])
elseif model == 5 then
- -- return formatters['multitonecolor("%s",%s,"%s","%s")'](cv[10],cv[11],cv[12],cv[13])
- return formatters['namedcolor("%s")'](cv[10])
+ return formatters['namedcolor("%s")'](name or cv[10])
else -- see ** in meta-ini.mkiv: return formatters["%s"]((cv[2]))
return formatters["(%s,%s,%s)"](cv[3],cv[4],cv[5])
end
@@ -698,7 +718,8 @@ local paletnamespace = getnamespace("colorpalet")
local function namedcolorattributes(name)
local space = texgetattribute(a_colormodel)
- local prefix = texgettoks("t_colo_prefix")
+ ----- prefix = texgettoks("t_colo_prefix")
+ local prefix = texgetmacro("currentcolorprefix")
local color
if prefix ~= "" then
color = valid[prefix..name]
@@ -734,7 +755,8 @@ end
colors.namedcolorattributes = namedcolorattributes -- can be used local
local function mpnamedcolor(name)
- return mpcolor(namedcolorattributes(name))
+ local model, ca, ta = namedcolorattributes(name)
+ return mpcolor(model,ca,ta,nil,name)
end
local function mpoptions(model,ca,ta,default) -- will move to mlib-col .. not really needed
@@ -1090,7 +1112,7 @@ implement {
implement {
name = "defineprocesscolordummy",
actions = defineprocesscolor,
- arguments = { "'d_u_m_m_y'", "string", false, false }
+ arguments = { "'c_o_l_o_r'", "string", false, false }
}
implement {
diff --git a/tex/context/base/mkiv/colo-ini.mkiv b/tex/context/base/mkiv/colo-ini.mkiv
index daee8ada6..7079322f7 100644
--- a/tex/context/base/mkiv/colo-ini.mkiv
+++ b/tex/context/base/mkiv/colo-ini.mkiv
@@ -592,22 +592,22 @@
% \the\everysetuppalet
% \colo_helpers_initialize_maintextcolor}
-\newtoks\t_colo_prefix % used in mp interface
+% \newtoks\t_colo_prefix % used in mp interface
\def\colo_palets_setup[#1]%
{\edef\currentcolorpalet{#1}%
\ifx\currentcolorpalet\empty
% seems to be a reset
\let\currentcolorprefix\empty
- \t_colo_prefix\emptytoks
+ %\t_colo_prefix\emptytoks
\else\ifcsname\??paletlist\currentcolorpalet\endcsname
\edef\currentcolorprefix{#1:}%
- \t_colo_prefix\expandafter{\currentcolorprefix}%
+ %\t_colo_prefix\expandafter{\currentcolorprefix}%
\else
\colo_helpers_show_message\m!colors7\currentcolorpalet
\let\currentcolorpalet\empty
\let\currentcolorprefix\empty
- \t_colo_prefix\emptytoks
+ %\t_colo_prefix\emptytoks
\fi\fi
\the\everysetuppalet
\colo_helpers_initialize_maintextcolor}
@@ -782,7 +782,12 @@
% Since we couple definitions, we could stick to one test. Todo. Same for mpcolor.
-\def\v_colo_dummy_name{d_u_m_m_y}
+\def\v_colo_dummy_name{c_o_l_o_r}
+
+\letvalue{\??colorattribute \v_colo_dummy_name}\empty
+\letvalue{\??transparencyattribute\v_colo_dummy_name}\empty
+\letvalue{\??colorsetter \v_colo_dummy_name}\empty
+\letvalue{\??transparencysetter \v_colo_dummy_name}\empty
\letvalue{\??colorsetter -}\empty % used?
\letvalue{\??transparencysetter-}\empty % used?
@@ -942,7 +947,7 @@
\def\colo_basics_defined_and_activated#1%
{\clf_defineprocesscolordummy{#1}% we could pass dummy here too
- \colo_basics_synchronize{d_u_m_m_y}%
+ \colo_basics_synchronize{\v_colo_dummy_name}%
\colo_helpers_activate_dummy}
\def\colo_basics_define_process
@@ -1058,7 +1063,7 @@
%D Here is a more efficient helper for pgf:
%D
-%D \starttying
+%D \starttyping
%D \startluacode
%D function commands.pgfxcolorspec(ca) -- {}{}{colorspace}{list}
%D local cv = attributes.colors.values[ca]
diff --git a/tex/context/base/mkiv/colo-run.lua b/tex/context/base/mkiv/colo-run.lua
index 2e4cca5ab..2e7ae08e3 100644
--- a/tex/context/base/mkiv/colo-run.lua
+++ b/tex/context/base/mkiv/colo-run.lua
@@ -14,7 +14,7 @@ local commands = commands
local context = context
local colors = attributes.colors
-local private = table.tohash { "d_u_m_m_y", "maintextcolor", "themaintextcolor" }
+local private = table.tohash { "c_o_l_o_r", "maintextcolor", "themaintextcolor" }
function commands.showcolorset(name)
local set = colors.setlist(name)
diff --git a/tex/context/base/mkiv/cont-log.mkiv b/tex/context/base/mkiv/cont-log.mkiv
index 8b4660f3a..f9fc6a8f7 100644
--- a/tex/context/base/mkiv/cont-log.mkiv
+++ b/tex/context/base/mkiv/cont-log.mkiv
@@ -133,7 +133,7 @@
\let\logofont\nullfont
-\loadmapfile[original-base.map] % stil needed? not if we assume afm
+% \loadmapfile[original-base.map] % stil needed? not if we assume afm
\unexpanded\def\setMFPfont% more sensitive for low level changes
{\font\logofont=logo%
@@ -205,7 +205,7 @@
\unexpanded\def\Lua {Lua}
\unexpanded\def\luajitTeX{luajit\wordboundary\TeX}
\unexpanded\def\metaTeX {meta\wordboundary\TeX}
-\unexpanded\def\XeTeX {X\lower.5\exheight\hbox{\kern-.15\emwidth\mirror{E}}\kern-.1667\emwidth\TeX}
+%unexpanded\def\XeTeX {X\lower.5\exheight\hbox{\kern-.15\emwidth\mirror{E}}\kern-.1667\emwidth\TeX}
% Adapted from a patch by Mojca:
@@ -237,40 +237,6 @@
\let\LuaTeX \luaTeX
\let\XETEX \XeTeX
-% \unexpanded\def\MkApproved % joke, not used so it might move
-% {\dontleavehmode\rotate
-% [\c!rotation={\ifnum\texengine=\luatexengine\cldcontext{45-45*\the\luatexversion/100}\else0\fi},
-% \c!align=\v!middle,
-% \c!foregroundstyle=\v!type,
-% \c!foregroundcolor=darkred,
-% \c!frame=\v!on,
-% \c!offset=1ex,
-% \c!background=\v!color,
-% \c!backgroundcolor=lightgray,
-% \c!framecolor=darkred,
-% \c!rulethickness=2pt]
-% {Mk\ifnum\texengine=\luatexengine IV\else II\fi\\approved}}
-
-% \unexpanded\def\luaTeX
-% {\dontleavehmode\begingroup
-% Lua%
-% \setbox0\hbox{oT}%
-% \setbox2\hbox{o\kern0ptT}%
-% \ifdim\wd0=\wd2
-% \setbox0\hbox dir TRT{To}%
-% \setbox2\hbox{T\kern0pto}%
-% \hskip\dimexpr\wd0-\wd2\relax
-% \fi
-% \TeX
-% \endgroup}
-%
-% a further iteration from the list, patched again
-
-% \ifx\fontalternative\s!it -\else
-% \ifx\fontalternative\s!sl -\else
-% \ifx\fontalternative\s!bi -\else
-% \ifx\fontalternative\s!bs -\fi\fi\fi\fi
-
\unexpanded\def\LuaTeX
{\dontleavehmode
\begingroup
@@ -317,6 +283,8 @@
\unexpanded\def\MPIV{MpIV}
\unexpanded\def\MPVI{MpVI}
+\unexpanded\def\LMTX{lmtx}
+
\appendtoks
\def\ConTeXt {ConTeXt}%
\def\MetaPost {MetaPost}%
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index 9cb893260..f8abf6fad 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -11,13 +11,27 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2018.04.04 00:51}
+\newcontextversion{2019.02.22 19:35}
%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}
+\writestatus\m!system{beware: some patches loaded from cont-new.mkiv}
+
+% math-ini.mkiv
+
+\ifdefined\t \else \unexpanded\def\t{\mathortext\text\mathtext} \fi
+\ifdefined\w \else \unexpanded\def\w{\mathortext\word\mathword} \fi
+
+\appendtoks
+ \let\t\mathtext
+ \let\w\mathword
+\to \everymathematics
+
+% \let\assumelongusagecs\relax % todo: fails on legends-001.tex
+
+% done
\protect \endinput
diff --git a/tex/context/base/mkiv/cont-run.lua b/tex/context/base/mkiv/cont-run.lua
index 9bd252e60..2634654fe 100644
--- a/tex/context/base/mkiv/cont-run.lua
+++ b/tex/context/base/mkiv/cont-run.lua
@@ -142,6 +142,7 @@ trackers.register("sandbox.tracecalls",sandbox.logcalls)
trackers.register("sandbox.tracefiles",sandbox.logfiles)
local sandboxing = environment.arguments.sandbox
+local debugging = environment.arguments.debug
if sandboxing then
@@ -170,15 +171,33 @@ if sandboxing then
\let\normalprimitive\relax
]]
-end
+ debug = {
+ traceback = traceback,
+ }
-local function processjob()
+ package.loaded.debug = debug
- environment.initializefilenames() -- todo: check if we really need to pre-prep the filename
+elseif debugging then
+
+ -- we keep debug
+
+else
+
+ debug = {
+ traceback = traceback,
+ getinfo = getinfo,
+ sethook = sethook,
+ }
+
+ package.loaded.debug = debug
+
+end
+
+local preparejob preparejob = function() -- tricky: we need a hook for this
local arguments = environment.arguments
- local suffix = environment.suffix
- local filename = environment.filename -- hm, not inputfilename !
+
+ environment.lmtxmode = CONTEXTLMTXMODE
if arguments.nosynctex then
luatex.synctex.setup {
@@ -222,6 +241,24 @@ local function processjob()
-- directives.enable("logs.errors",arguments.errors)
-- end
+ preparejob = function() end
+
+ job.prepare = preparejob
+
+end
+
+job.prepare = preparejob
+
+local function processjob()
+
+ environment.initializefilenames() -- todo: check if we really need to pre-prep the filename
+
+ local arguments = environment.arguments
+ local suffix = environment.suffix
+ local filename = environment.filename -- hm, not inputfilename !
+
+ preparejob()
+
if not filename or filename == "" then
-- skip
elseif suffix == "xml" or arguments.forcexml then
@@ -285,7 +322,6 @@ local function processjob()
-- \writestatus{system}{processing as tex}
-- We have a regular tex file so no \starttext yet as we can
-- load fonts.
-
-- context.enabletrackers { "resolvers.*" }
context.input(filename)
-- context.disabletrackers { "resolvers.*" }
diff --git a/tex/context/base/mkiv/cont-run.mkiv b/tex/context/base/mkiv/cont-run.mkiv
index b650be67d..f841ce530 100644
--- a/tex/context/base/mkiv/cont-run.mkiv
+++ b/tex/context/base/mkiv/cont-run.mkiv
@@ -25,19 +25,29 @@
\let\synctexsetfilename \clf_synctexsetfilename
\let\synctexresetfilename\clf_synctexresetfilename
\let\synctexblockfilename\clf_synctexblockfilename
-\let\synctexpause \clf_synctexpause
-\let\synctexresume \clf_synctexresume
-\appendtoks\clf_synctexpause \to\everybeforeoutput
-\appendtoks\clf_synctexresume\to\everyafteroutput
+\let\synctexpause \donothing
+\let\synctexresume \donothing
+\let\synctexpushline\donothing
+\let\synctexpopline \donothing
+
+\appendtoks\synctexpause \to\everybeforeoutput
+\appendtoks\synctexresume\to\everyafteroutput
\unexpanded\def\setupsynctex[#1]%
{\begingroup
\getdummyparameters[\c!state=\v!stop,\c!method=\v!max,#1]%
+ \edef\p_state{\dummyparameter\c!state}%
\clf_setupsynctex
- state {\dummyparameter\c!state}%
+ state {\p_state}%
method {\dummyparameter\c!method}%
\relax
+ \ifx\p_state\v!start
+ \glet\synctexpause \clf_synctexpause
+ \glet\synctexresume \clf_synctexresume
+ \glet\synctexpushline\clf_synctexpushline
+ \glet\synctexpopline \clf_synctexpopline
+ \fi
\endgroup}
\unexpanded\def\blocksynctexfile[#1]%
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index 9a52cfe78..cd0170587 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -42,9 +42,13 @@
%D has to match \type {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2018.04.04 00:51}
+\edef\contextversion{2019.02.22 19:35}
\edef\contextkind {beta}
+%D Kind of special:
+
+\chardef\contextlmtxmode\directlua{tex.print(CONTEXTLMTXMODE or 0)}\relax
+
%D For those who want to use this:
\let\fmtname \contextformat
@@ -77,8 +81,8 @@
%D We just quit if new functionality is expected.
-\ifnum\luatexversion<105 % also change message
- \writestatus{!!!!}{Your luatex binary is too old, you need at least version 1.05!}
+\ifnum\luatexversion<109 % also change message
+ \writestatus{!!!!}{Your luatex binary is too old, you need at least version 1.09!}
\expandafter\end
\fi
@@ -99,6 +103,7 @@
\loadmarkfile{luat-cod}
\loadmarkfile{luat-bas}
\loadmarkfile{luat-lib}
+\loadmarkfile{luat-soc}
\loadmarkfile{catc-ini}
\loadmarkfile{catc-act}
@@ -106,6 +111,7 @@
\loadmarkfile{catc-ctx}
\loadmarkfile{catc-sym}
+\loadmarkfile{toks-ini}
\loadmarkfile{cldf-ini}
% \tracecatcodetables
@@ -114,7 +120,7 @@
% \unexpanded long before etex came around.
\loadmarkfile{luat-ini}
-\loadmarkfile{toks-ini}
+\loadmarkfile{toks-scn}
\loadmarkfile{syst-aux}
\loadmarkfile{syst-lua}
@@ -125,13 +131,18 @@
\loadmarkfile{luat-usr}
-% \loadmarkfile{luat-ini} % moved up
-% \loadmarkfile{toks-ini} % moved up
-
\loadmkvifile{file-ini}
\loadmkvifile{file-res}
\loadmkvifile{file-lib}
+\doifelsefileexists{core-lmt.mkiv} {\loadmarkfile{core-lmt}} {}
+
+% needs more checking for clashes:
+%
+% no need to register, just execute once, slightly faster
+%
+% \doifelsefileexists{l-macro-imp-codes.lua}{\registerctxluafile{l-macro-imp-codes}{}}{}
+
\loadmarkfile{supp-dir}
\loadmarkfile{char-utf} % generic code (i.e. not much tex) ... could become unic-ini
@@ -153,6 +164,7 @@
% \loadmarkfile{luat-ini}
\loadmarkfile{toks-tra}
+\loadmarkfile{toks-aux}
%loadmarkfile{toks-map} % obsolete, never used
\loadmarkfile{attr-ini}
@@ -170,6 +182,8 @@
\loadmarkfile{node-mig}
%loadmarkfile{node-pag}
+\loadmarkfile{driv-ini}
+
\loadmarkfile{back-ini}
\loadmarkfile{attr-col}
@@ -202,6 +216,7 @@
\loadmkvifile{file-syn}
\loadmkvifile{file-mod}
+\loadmarkfile{core-sys}
\loadmarkfile{core-con}
\loadmarkfile{cont-fil}
@@ -274,7 +289,6 @@
\loadmarkfile{spac-lin}
\loadmarkfile{spac-pag}
\loadmarkfile{spac-par}
-%loadmarkfile{spac-adj} % no longer needed
\loadmarkfile{spac-def}
\loadmkvifile{spac-prf}
\loadmarkfile{spac-grd}
@@ -296,7 +310,7 @@
\loadmarkfile{strc-lab}
\loadmarkfile{strc-syn}
-\loadmarkfile{core-sys}
+% \loadmarkfile{core-sys}
\loadmarkfile{page-var}
\loadmkvifile{page-otr}
@@ -319,9 +333,11 @@
\loadmarkfile{page-pst}
\loadmkvifile{page-mbk}
-\loadmarkfile{page-mul} % partly overloaded
-\loadmarkfile{page-mix} % new
-\loadmarkfile{page-set}
+%loadmarkfile{page-mul} % \usecolumns[old-multicolumns]
+\loadmarkfile{page-mix}
+\loadmarkfile{page-smp}
+%loadmarkfile{page-set} % \usecolumns[old-columnsets]
+\loadmarkfile{page-cst}
\loadmarkfile{page-pcl} % new
\loadmarkfile{pack-lyr}
\loadmarkfile{pack-pos}
@@ -507,6 +523,7 @@
\loadmkvifile{strc-not}
\loadmkvifile{strc-lnt}
+\loadmkivfile{strc-usr}
\loadmarkfile{pack-com}
\loadmarkfile{typo-del}
@@ -547,7 +564,7 @@
\loadmarkfile{cont-log}
-\loadmarkfile{task-ini}
+% \loadmarkfile{task-ini}
\loadmarkfile{cldf-ver} % verbatim, this can come late
\loadmarkfile{cldf-com} % commands, this can come late
@@ -565,13 +582,24 @@
\loadmarkfile{back-exp}
\loadmarkfile{back-pdf} % actually, this one should load the next three using document.arguments.backend
+
\loadmarkfile{mlib-pdf}
\loadmarkfile{mlib-pps}
\loadmarkfile{meta-pdf}
+\loadmarkfile{meta-blb}
\loadmarkfile{grph-epd}
+\loadmarkfile{math-inc} % an experiment
+\loadmarkfile{publ-inc} % an experiment
+
+\loadmarkfile{task-ini}
+
+\loadmarkfile{syst-cmp} % compatibility stuff moved here
+
\loadmarkfile{cont-run} % the main runner (used in cont-yes.mkiv)
+\doifelsefileexists{driv-shp.mkiv} {\loadmarkfile{driv-shp}} {}
+
\setupcurrentlanguage[\defaultlanguagetag]
\prependtoks
@@ -582,6 +610,14 @@
\ctxlua{statistics.stoptiming(statistics)}%
\to \everyjob
+% \appendtoks
+% \ctxlua{job.prepare()}%
+% \to \everyjob
+
+% \appendtoks
+% \enabletrackers[*]%
+% \to \everyjob
+
\appendtoks
\ctxlua{statistics.savefmtstatus("\jobname","\contextversion","context.mkiv","\contextkind","\contextbanner")}% can become automatic
\to \everydump
diff --git a/tex/context/base/mkiv/core-con.lua b/tex/context/base/mkiv/core-con.lua
index 87b4c063e..3829efc9c 100644
--- a/tex/context/base/mkiv/core-con.lua
+++ b/tex/context/base/mkiv/core-con.lua
@@ -16,7 +16,7 @@ slower but look nicer this way.</p>
<p>Some code may move to a module in the language namespace.</p>
--ldx]]--
-local floor, date, time, concat = math.floor, os.date, os.time, table.concat
+local floor, osdate, ostime, concat = math.floor, os.date, os.time, table.concat
local lower, upper, rep, match, gsub = string.lower, string.upper, string.rep, string.match, string.gsub
local utfchar, utfbyte = utf.char, utf.byte
local tonumber, tostring, type, rawset = tonumber, tostring, type, rawset
@@ -33,6 +33,7 @@ local setmetatableindex = table.setmetatableindex
local formatters = string.formatters
local variables = interfaces.variables
local constants = interfaces.constants
+local addformatter = utilities.strings.formatters.add
local texset = tex.set
@@ -42,6 +43,9 @@ local converters = converters
languages = languages or { }
local languages = languages
+local helpers = converters.helpers or { }
+converters.helpers = helpers
+
local ctx_labeltext = context.labeltext
local ctx_LABELTEXT = context.LABELTEXT
local ctx_space = context.space
@@ -304,14 +308,14 @@ local function leapyear(year)
end
local function textime()
- return tonumber(date("%H")) * 60 + tonumber(date("%M"))
+ return tonumber(osdate("%H")) * 60 + tonumber(osdate("%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
+function converters.year () return osdate("%Y") end
+function converters.month () return osdate("%m") end
+function converters.hour () return osdate("%H") end
+function converters.minute() return osdate("%M") end
+function converters.second() return osdate("%S") end
converters.weekday = weekday
converters.isleapyear = isleapyear
@@ -323,11 +327,11 @@ implement { name = "weekday", actions = { weekday, context }, arguments = { "i
implement { name = "leapyear", actions = { leapyear, context }, arguments = { "integer" } }
implement { name = "nofdays", actions = { nofdays, context }, arguments = { "integer", "integer" } }
-implement { name = "year", actions = { date, context }, arguments = "'%Y'" }
-implement { name = "month", actions = { date, context }, arguments = "'%m'" }
-implement { name = "hour", actions = { date, context }, arguments = "'%H'" }
-implement { name = "minute", actions = { date, context }, arguments = "'%M'" }
-implement { name = "second", actions = { date, context }, arguments = "'%S'" }
+implement { name = "year", actions = { osdate, context }, arguments = "'%Y'" }
+implement { name = "month", actions = { osdate, context }, arguments = "'%m'" }
+implement { name = "hour", actions = { osdate, context }, arguments = "'%H'" }
+implement { name = "minute", actions = { osdate, context }, arguments = "'%M'" }
+implement { name = "second", actions = { osdate, context }, arguments = "'%S'" }
implement { name = "textime", actions = { textime, context } }
implement {
@@ -1222,45 +1226,108 @@ setmetatableindex(months, function(t,k) return "unknown" end)
setmetatableindex(days, function(t,k) return "unknown" end)
setmetatableindex(monthmnems, function(t,k) return months[k] .. ":mnem" end)
-local function dayname(n)
- return days[n]
-end
+do
-local function weekdayname(day,month,year)
- return days[weekday(day,month,year)]
-end
+ local function dayname(n)
+ ctx_labeltext(days[n])
+ end
-local function monthname(n)
- return months[n]
-end
+ local function weekdayname(day,month,year)
+ ctx_labeltext(days[weekday(day,month,year)])
+ end
-local function monthmnem(n)
- return monthmnems[n]
-end
+ local function monthname(n)
+ ctx_labeltext(months[n])
+ end
-implement {
- name = "dayname",
- actions = { dayname, ctx_labeltext },
- arguments = "integer",
-}
+ local function monthmnem(n)
+ ctx_labeltext(monthmnems[n])
+ end
-implement {
- name = "weekdayname",
- actions = { weekdayname, ctx_labeltext },
- arguments = { "integer", "integer", "integer" }
-}
+ implement {
+ name = "dayname",
+ actions = dayname,
+ arguments = "integer",
+ }
-implement {
- name = "monthname",
- actions = { monthname, ctx_labeltext },
- arguments = { "integer" }
-}
+ implement {
+ name = "weekdayname",
+ actions = weekdayname,
+ arguments = { "integer", "integer", "integer" }
+ }
-implement {
- name = "monthmnem",
- actions = { monthmnem, ctx_labeltext },
- arguments = { "integer" }
-}
+ implement {
+ name = "monthname",
+ actions = monthname,
+ arguments = { "integer" }
+ }
+
+ implement {
+ name = "monthmnem",
+ actions = monthmnem,
+ arguments = { "integer" }
+ }
+
+ local f_monthlong = formatters["\\monthlong{%s}"]
+ local f_monthshort = formatters["\\monthshort{%s}"]
+ local f_weekday = formatters["\\weekday{%s}"]
+ local f_dayoftheweek = formatters["\\dayoftheweek{%s}{%s}{%s}"]
+
+ local function tomonthlong (m) return f_monthlong (tonumber(m) or 1) end
+ local function tomonthshort(m) return f_monthshort(tonumber(m) or 1) end
+ local function toweekday (d) return f_weekday (tonumber(d) or 1) end
+
+ local function todayoftheweek(d,m,y)
+ return f_dayoftheweek(tonumber(d) or 1,tonumber(m) or 1,tonumber(y) or 2000)
+ end
+
+ addformatter(formatters,"monthlong", [[tomonthlong(%s)]], { tomonthlong = tomonthlong })
+ addformatter(formatters,"monthshort", [[tomonthshort(%s)]], { tomonthshort = tomonthshort })
+ addformatter(formatters,"weekday", [[toweekday(%s)]], { toweekday = toweekday })
+ addformatter(formatters,"dayoftheweek",[[todayoftheweek(%s,%s,%s)]],{ todayoftheweek = todayoftheweek })
+
+ -- using %t is slower, even with caching as we seldom use > 3 items per epoch
+
+ local function toeyear (e) return osdate("%Y",tonumber(e)) end
+ local function toemonth (e) return osdate("%m",tonumber(e)) end
+ local function toeday (e) return osdate("%d",tonumber(e)) end
+ local function toeminute(e) return osdate("%M",tonumber(e)) end
+ local function toesecond(e) return osdate("%S",tonumber(e)) end
+
+ local function toemonthlong(e)
+ return f_monthlong(tonumber(osdate("%m",tonumber(e))))
+ end
+
+ local function toemonthshort(e)
+ return f_monthshort(tonumber(osdate("%m",tonumber(e))))
+ end
+
+ local function toeweek(e) -- we run from 1-7 not 0-6
+ return tostring(tonumber(osdate("%w",tonumber(e)))+1)
+ end
+
+ local function toeweekday(e)
+ return f_weekday(tonumber(osdate("%w",tonumber(e)))+1)
+ end
+
+ local function toedate(format,e)
+ return osdate(format,tonumber(e))
+ end
+
+ addformatter(formatters,"eyear", [[toeyear(%s)]], { toeyear = toeyear })
+ addformatter(formatters,"emonth", [[toemonth(%s)]], { toemonth = toemonth })
+ addformatter(formatters,"eday", [[toeday(%s)]], { toeday = toeday })
+ addformatter(formatters,"eweek", [[toeweek(%s)]], { toeweek = toeweek })
+ addformatter(formatters,"eminute", [[toeminute(%s)]], { toeminute = toeminute })
+ addformatter(formatters,"esecond", [[toesecond(%s)]], { toesecond = toesecond })
+
+ addformatter(formatters,"emonthlong", [[toemonthlong(%s)]], { toemonthlong = toemonthlong })
+ addformatter(formatters,"emonthshort", [[toemonthshort(%s)]], { toemonthshort = toemonthshort })
+ addformatter(formatters,"eweekday", [[toeweekday(%s)]], { toeweekday = toeweekday })
+
+ addformatter(formatters,"edate", [[toedate(%s,%s)]], { toedate = toedate })
+
+end
-- a prelude to a function that we can use at the lua end
@@ -1287,125 +1354,146 @@ local variants = {
jalali = setmetatableindex(function(t,k) return months[k] .. ":jalali" end),
}
-local function 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 = tex.year
- local month = tex.month
- local day = tex.day
- local auto = true
- if currentlanguage == "" then
- currentlanguage = false
- end
- for i=1,#list do
- local entry = list[i]
- local convert = dateconverters[entry]
- if convert then
- year, month, day = convert(year,month,day)
- else
- local tag, plus = splitlabel(entry)
- local ordinal, mnemonic, whatordinal, highordinal = false, false, nil, false
- if not tag then
- tag = entry
- elseif plus == "+" or plus == "ord" then
- ordinal = true
- elseif plus == "++" or plus == "highord" then
- ordinal = true
- highordinal = true
- -- elseif plus == "mnem" then
- -- mnemonic = true
- elseif plus then -- elseif plus == "mnem" then
- mnemonic = variants[plus]
- end
- if not auto and spaced[tag] then
- ctx_space()
- end
- auto = false
- if tag == v_year or tag == "y" or tag == "Y" then
- context(year)
- elseif tag == "yy" or tag == "YY" then
- context("%02i",year % 100)
- elseif tag == v_month or tag == "m" then
- if currentlanguage == false then
- context(Word(months[month]))
- elseif mnemonic then
- ctx_labeltext(variables[mnemonic[month]])
- else
- ctx_labeltext(variables[months[month]])
+do
+
+ local function currentdate(str,currentlanguage,year,month,day) -- 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 = tex.year
+ -- local month = tex.month
+ -- local day = tex.day
+ local auto = true
+ if currentlanguage == "" then
+ currentlanguage = false
+ end
+ for i=1,#list do
+ local entry = list[i]
+ local convert = dateconverters[entry]
+ if convert then
+ year, month, day = convert(year,month,day)
+ else
+ local tag, plus = splitlabel(entry)
+ local ordinal, mnemonic, whatordinal, highordinal = false, false, nil, false
+ if not tag then
+ tag = entry
+ elseif plus == "+" or plus == "ord" then
+ ordinal = true
+ elseif plus == "++" or plus == "highord" then
+ ordinal = true
+ highordinal = true
+ -- elseif plus == "mnem" then
+ -- mnemonic = true
+ elseif plus then -- elseif plus == "mnem" then
+ mnemonic = variants[plus]
end
- elseif tag == v_MONTH then
- if currentlanguage == false then
- context(Word(variables[months[month]]))
- elseif mnemonic then
- ctx_LABELTEXT(variables[mnemonic[month]])
- else
- ctx_LABELTEXT(variables[months[month]])
+ if not auto and spaced[tag] then
+ ctx_space()
end
- elseif tag == "mm" then
- context("%02i",month)
- elseif tag == "M" then
- context(month)
- elseif tag == v_day or tag == "d" then
- if currentlanguage == false then
+ auto = false
+ if tag == v_year or tag == "y" or tag == "Y" then
+ context(year)
+ elseif tag == "yy" or tag == "YY" then
+ context("%02i",year % 100)
+ elseif tag == v_month or tag == "m" then
+ if currentlanguage == false then
+ context(Word(months[month]))
+ elseif mnemonic then
+ ctx_labeltext(variables[mnemonic[month]])
+ else
+ ctx_labeltext(variables[months[month]])
+ end
+ elseif tag == v_MONTH then
+ if currentlanguage == false then
+ context(Word(variables[months[month]]))
+ elseif mnemonic then
+ ctx_LABELTEXT(variables[mnemonic[month]])
+ else
+ ctx_LABELTEXT(variables[months[month]])
+ end
+ elseif tag == "mm" then
+ context("%02i",month)
+ elseif tag == "M" then
+ context(month)
+ elseif tag == v_day or tag == "d" then
+ if currentlanguage == false then
+ context(day)
+ else
+ ctx_convertnumber(v_day,day) -- why not direct
+ end
+ whatordinal = day
+ elseif tag == "dd" then
+ context("%02i",day)
+ whatordinal = day
+ elseif tag == "D" then
context(day)
- else
- ctx_convertnumber(v_day,day) -- why not direct
+ whatordinal = day
+ elseif tag == v_weekday or tag == "w" then
+ local wd = weekday(day,month,year)
+ if currentlanguage == false then
+ context(Word(days[wd]))
+ else
+ ctx_labeltext(variables[days[wd]])
+ end
+ elseif tag == v_WEEKDAY then
+ local wd = weekday(day,month,year)
+ if currentlanguage == false then
+ context(Word(days[wd]))
+ else
+ ctx_LABELTEXT(variables[days[wd]])
+ end
+ elseif tag == "W" then
+ context(weekday(day,month,year))
+ elseif tag == v_referral then
+ context("%04i%02i%02i",year,month,day)
+ elseif tag == v_space or tag == "\\ " then
+ ctx_space()
+ auto = true
+ elseif tag ~= "" then
+ context(tag)
+ auto = true
end
- whatordinal = day
- elseif tag == "dd" then
- context("%02i",day)
- whatordinal = day
- elseif tag == "D" then
- context(day)
- whatordinal = day
- elseif tag == v_weekday or tag == "w" then
- local wd = weekday(day,month,year)
- if currentlanguage == false then
- context(Word(days[wd]))
- else
- ctx_labeltext(variables[days[wd]])
- end
- elseif tag == v_WEEKDAY then
- local wd = weekday(day,month,year)
- if currentlanguage == false then
- context(Word(days[wd]))
- else
- ctx_LABELTEXT(variables[days[wd]])
- end
- elseif tag == "W" then
- context(weekday(day,month,year))
- elseif tag == v_referral then
- context("%04i%02i%02i",year,month,day)
- elseif tag == v_space or tag == "\\ " then
- ctx_space()
- auto = true
- elseif tag ~= "" then
- context(tag)
- auto = true
- end
- if ordinal and whatordinal then
- if currentlanguage == false then
- -- ignore
- else
- context[highordinal and "highordinalstr" or "ordinalstr"](converters.ordinal(whatordinal,currentlanguage))
+ if ordinal and whatordinal then
+ if currentlanguage == false then
+ -- ignore
+ else
+ context[highordinal and "highordinalstr" or "ordinalstr"](converters.ordinal(whatordinal,currentlanguage))
+ end
end
end
end
end
-end
+ implement {
+ name = "currentdate",
+ arguments = { "string", "string", "string", "integer", "integer", "integer" },
+ actions = function(pattern,default,language,year,month,day)
+ currentdate(
+ pattern == "" and default or pattern,
+ language == "" and false or language,
+ year, month, day
+ )
+ end,
+ }
+
+ local function todate(s,y,m,d)
+ if y or m or d then
+ return formatters["\\date[y=%s,m=%s,d=%s][%s]\\relax"](y or "",m or "",d or "",s or "")
+ else
+ return formatters["\\currentdate[%s]\\relax"](s)
+ end
+ end
+
+ addformatter(formatters,"date", [[todate(...)]], { todate = todate })
+ -- context("one: %4!date!","MONTH",2020,12,11) context.par()
+ -- context("one: %4!date!","month",2020,12,11) context.par()
+ -- context("one: %4!date!","year,-,mm,-,dd",2020,12,11) context.par()
-implement {
- name = "currentdate",
- arguments = "3 strings",
- actions = function(pattern,default,language)
- currentdate(
- pattern == "" and default or pattern,
- language == "" and false or language
- )
- end,
-}
+ -- context("two: %3!date!","MONTH",false,12) context.par()
+ -- context("two: %3!date!","month",false,12) context.par()
+ -- context("two: %3!date!","year,-,mm,-,dd",false,12) context.par()
+
+end
implement {
name = "unihex",
@@ -1586,3 +1674,4 @@ implement {
}
}
}
+
diff --git a/tex/context/base/mkiv/core-con.mkiv b/tex/context/base/mkiv/core-con.mkiv
index b4f247fcb..303fb1291 100644
--- a/tex/context/base/mkiv/core-con.mkiv
+++ b/tex/context/base/mkiv/core-con.mkiv
@@ -190,10 +190,10 @@
%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
-\savenormalmeaning\month
-\savenormalmeaning\day
+% \savenormalmeaning\time
+% \savenormalmeaning\year
+% \savenormalmeaning\month
+% \savenormalmeaning\day
%D \macros
%D {month,MONTH}
@@ -218,7 +218,7 @@
%D \showsetup{month}
%D \showsetup{MONTH}
-\let\month \monthlong
+\let\month\monthlong
\unexpanded\def\MONTH #1{\WORD{\month {#1}}}
\unexpanded\def\MONTHLONG #1{\WORD{\monthlong {#1}}}
@@ -414,30 +414,43 @@
{\dosingleempty\syst_converters_current_date}
\def\syst_converters_current_date[#1]%
- {\begingroup
+ {\dontleavehmode
+ \begingroup
\the\everycurrentdate
- \clf_currentdate{#1}{\currentdatespecification}{\labellanguage}%
+ \clf_currentdate
+ {#1}{\currentdatespecification}{\labellanguage}%
+ \normalyear\normalmonth\normalday
\endgroup}
\unexpanded\def\date
{\dodoubleempty\syst_converters_date}
\def\syst_converters_date[#1][#2]%
- {\begingroup
+ {\dontleavehmode
+ \begingroup
+ \scratchcounterone \normalyear
+ \scratchcountertwo \normalmonth
+ \scratchcounterthree\normalday
\iffirstargument
- \letdummyparameter\c!d\normalday
- \letdummyparameter\c!m\normalmonth
- \letdummyparameter\c!y\normalyear
+ \letdummyparameter\c!y\empty
+ \letdummyparameter\c!m\empty
+ \letdummyparameter\c!d\empty
\getdummyparameters[#1]%
- \normalday \directdummyparameter\c!d\relax
- \normalmonth\directdummyparameter\c!m\relax
- \normalyear \directdummyparameter\c!y\relax
+ \edef\temp{\dummyparameter\c!y}\ifx\temp\empty\else\scratchcounterone \temp\fi
+ \edef\temp{\dummyparameter\c!m}\ifx\temp\empty\else\scratchcountertwo \temp\fi
+ \edef\temp{\dummyparameter\c!d}\ifx\temp\empty\else\scratchcounterthree\temp\fi
+ \relax
\fi
- \syst_converters_current_date[#2]%
+ \the\everycurrentdate
+ \clf_currentdate
+ {#2}{\currentdatespecification}{\labellanguage}%
+ \scratchcounterone\scratchcountertwo\scratchcounterthree
\endgroup}
\def\rawdate[#1]% expandable and no labels
- {\clf_currentdate{#1}{\currentdatespecification}{}}
+ {\clf_currentdate
+ {#1}{\currentdatespecification}{}%
+ \normalyear\normalmonth\normalday}
%D \macros
%D {currenttime}
@@ -454,7 +467,7 @@
\let\currentminute\!!plusone
\let\currentsecond\!!plusone
-\def\currenttimespecification{h,:,m}
+% \def\currenttimespecification{h,:,m}
\unexpanded\def\currenttime
{\doifelsenextoptional\syst_converters_current_time_yes\syst_converters_current_time_nop}
@@ -805,61 +818,119 @@
\ifdefined\symbol \else \def\symbol[#1]{#1} \fi % todo
+% \defineconversion
+% [set 0]
+% [{\symbol[bullet]},
+% {\symbol[dash]},
+% {\symbol[star]},
+% {\symbol[triangle]},
+% {\symbol[circle]},
+% {\symbol[medcircle]},
+% {\symbol[bigcircle]},
+% {\symbol[square]},
+% {\symbol[checkmark]}]
+
+% \defineconversion
+% [set 1]
+% [\mathematics{\star},
+% \mathematics{\star\star},
+% \mathematics{\star\star\star},
+% \mathematics{\ddagger},
+% \mathematics{\ddagger\ddagger},
+% \mathematics{\ddagger\ddagger\ddagger},
+% \mathematics{\ast},
+% \mathematics{\ast\ast},
+% \mathematics{\ast\ast\ast}]
+%
+% \defineconversion
+% [set 2]
+% [\mathematics{\ast},
+% \mathematics{\dag},
+% \mathematics{\ddag},
+% \mathematics{\ast\ast},
+% \mathematics{\dag\dag},
+% \mathematics{\ddag\ddag},
+% \mathematics{\ast\ast\ast},
+% \mathematics{\dag\dag\dag},
+% \mathematics{\ddag\ddag\ddag},
+% \mathematics{\ast\ast\ast\ast},
+% \mathematics{\dag\dag\dag\dag},
+% \mathematics{\ddag\ddag\ddag\ddag}]
+%
+% \defineconversion
+% [set 3]
+% [\mathematics{\star},
+% \mathematics{\star\star},
+% \mathematics{\star\star\star},
+% \mathematics{\ddagger},
+% \mathematics{\ddagger\ddagger},
+% \mathematics{\ddagger\ddagger\ddagger},
+% \mathematics{\P},
+% \mathematics{\P\P},
+% \mathematics{\P\P\P},
+% \mathematics{\S},
+% \mathematics{\S\S},
+% \mathematics{\S\S\S},
+% \mathematics{\ast},
+% \mathematics{\ast\ast},
+% \mathematics{\ast\ast\ast}]
+
\defineconversion
[set 0]
- [{\symbol[bullet]},
- {\symbol[dash]},
- {\symbol[star]},
- {\symbol[triangle]},
- {\symbol[circle]},
- {\symbol[medcircle]},
- {\symbol[bigcircle]},
- {\symbol[square]}]
+ [\symbol{bullet},
+ \symbol{dash},
+ \symbol{star},
+ \symbol{triangle},
+ \symbol{circle},
+ \symbol{medcircle},
+ \symbol{bigcircle},
+ \symbol{square},
+ \symbol{checkmark}]
\defineconversion
[set 1]
- [\mathematics{\star},
- \mathematics{\star\star},
- \mathematics{\star\star\star},
- \mathematics{\ddagger},
- \mathematics{\ddagger\ddagger},
- \mathematics{\ddagger\ddagger\ddagger},
- \mathematics{\ast},
- \mathematics{\ast\ast},
- \mathematics{\ast\ast\ast}]
+ [\textormathchars{⋆},
+ \textormathchars{⋆⋆},
+ \textormathchars{⋆⋆⋆},
+ \textormathchars{‡},
+ \textormathchars{‡‡},
+ \textormathchars{‡‡‡},
+ \textormathchars{∗},
+ \textormathchars{∗∗},
+ \textormathchars{∗∗∗}]
\defineconversion
[set 2]
- [\mathematics{*},
- \mathematics{\dag},
- \mathematics{\ddag},
- \mathematics{**},
- \mathematics{\dag\dag},
- \mathematics{\ddag\ddag},
- \mathematics{***},
- \mathematics{\dag\dag\dag},
- \mathematics{\ddag\ddag\ddag},
- \mathematics{****},
- \mathematics{\dag\dag\dag\dag},
- \mathematics{\ddag\ddag\ddag\ddag}]
+ [\textormathchars{∗},
+ \textormathchars{†},
+ \textormathchars{‡},
+ \textormathchars{∗∗},
+ \textormathchars{††},
+ \textormathchars{‡‡},
+ \textormathchars{∗∗∗},
+ \textormathchars{†††},
+ \textormathchars{‡‡‡},
+ \textormathchars{∗∗∗∗},
+ \textormathchars{††††},
+ \textormathchars{‡‡‡‡}]
\defineconversion
[set 3]
- [\mathematics{\star},
- \mathematics{\star\star},
- \mathematics{\star\star\star},
- \mathematics{\ddagger},
- \mathematics{\ddagger\ddagger},
- \mathematics{\ddagger\ddagger\ddagger},
- \mathematics{\P},
- \mathematics{\P\P},
- \mathematics{\P\P\P},
- \mathematics{\S},
- \mathematics{\S\S},
- \mathematics{\S\S\S},
- \mathematics{\ast},
- \mathematics{\ast\ast},
- \mathematics{\ast\ast\ast}]
+ [\textormathchars{⋆},
+ \textormathchars{⋆⋆},
+ \textormathchars{⋆⋆⋆},
+ \textormathchars{‡},
+ \textormathchars{‡‡},
+ \textormathchars{‡‡‡},
+ \textormathchars{¶},
+ \textormathchars{¶¶},
+ \textormathchars{¶¶¶},
+ \textormathchars{§},
+ \textormathchars{§§},
+ \textormathchars{§§§},
+ \textormathchars{∗},
+ \textormathchars{∗∗},
+ \textormathchars{∗∗∗}]
%D Iteration of suggestion by WS on mailinglist 2010.12.22:
%D
@@ -888,4 +959,23 @@
data {#1}%
\relax}
+%D For those who sart counting at zero:
+%D
+%D \starttyping
+%D \defineconversionset [zero] [n,zero] [n]
+%D
+%D \setuphead [sectionconversionset=zero]
+%D
+%D \starttext
+%D \startchapter [title=Introduction]
+%D \startsection [title=First topic] \stopsection
+%D \startsection [title=Second topic] \stopsection
+%D \stopchapter
+%D \stoptext
+%D \stoptyping
+
+\def\zeronumberconversion#1{\number\numexpr#1-\plusone\relax}
+
+\defineconversion [zero] [\zeronumberconversion]
+
\protect \endinput
diff --git a/tex/context/base/mkiv/core-dat.lua b/tex/context/base/mkiv/core-dat.lua
index fa4d089d0..b49750159 100644
--- a/tex/context/base/mkiv/core-dat.lua
+++ b/tex/context/base/mkiv/core-dat.lua
@@ -15,6 +15,7 @@ local tonumber, tostring, type = tonumber, tostring, type
local context = context
local commands = commands
+local ctx_latelua = context.latelua
local trace_datasets = false trackers.register("job.datasets" , function(v) trace_datasets = v end)
local trace_pagestates = false trackers.register("job.pagestates", function(v) trace_pagestates = v end)
@@ -35,6 +36,7 @@ local v_yes = interfaces.variables.yes
local new_latelua = nodes.pool.latelua
local implement = interfaces.implement
+local getnamespace = interfaces.getnamespace
local collected = allocate()
local tobesaved = allocate()
@@ -106,6 +108,9 @@ end
datasets.setdata = setdata
function datasets.extend(name,tag)
+ if type(name) == "table" then
+ name, tag = name.name, name.tag
+ end
local set = sets[name]
local order = set.order + 1
local realpage = texgetcount("realpageno")
@@ -146,10 +151,8 @@ local function setdataset(settings)
local name, tag = setdata(settings)
if settings.delay ~= v_yes then
--
- elseif type(tag) == "number" then
- context(new_latelua(formatters["job.datasets.extend(%q,%i)"](name,tag)))
else
- context(new_latelua(formatters["job.datasets.extend(%q,%q)"](name,tag)))
+ context(new_latelua { action = job.datasets.extend, name = name, tag = tag })
end
end
@@ -242,9 +245,7 @@ local function setstate(settings)
return name, tag, data
end
-pagestates.setstate = setstate
-
-function pagestates.extend(name,tag)
+local function extend(name,tag)
local realpage = texgetcount("realpageno")
if trace_pagestates then
report_pagestate("action %a, name %a, tag %a, preset %a","synchronize",name,tag,realpage)
@@ -252,7 +253,7 @@ function pagestates.extend(name,tag)
tobesaved[name][tag] = realpage
end
-function pagestates.realpage(name,tag,default)
+local function realpage(name,tag,default)
local t = collected[name]
if t then
t = t[tag] or t[tonumber(tag)]
@@ -267,21 +268,36 @@ function pagestates.realpage(name,tag,default)
return default
end
-local function setpagestate(settings)
- local name, tag, data = setstate(settings)
- if type(tag) == "number" then
- context(new_latelua(formatters["job.pagestates.extend(%q,%i)"](name,tag)))
- else
- context(new_latelua(formatters["job.pagestates.extend(%q,%q)"](name,tag)))
- end
-end
-
-local function pagestaterealpage(name,tag)
+local function realpageorder(name,tag)
local t = collected[name]
- t = t and (t[tag] or t[tonumber(tag)])
if t then
- context(t)
+ local p = t[tag]
+ if p then
+ local n = 1
+ for i=tag-1,1,-1 do
+ if t[i] == p then
+ n = n +1
+ end
+ end
+ return n
+ end
end
+ return 0
+end
+
+pagestates.setstate = setstate
+pagestates.extend = extend
+pagestates.realpage = realpage
+pagestates.realpageorder = realpageorder
+
+function pagestates.countervalue(name)
+ return name and texgetcount(getnamespace("pagestatecounter") .. name) or 0
+end
+
+local function setpagestate(settings)
+ local name, tag = setstate(settings)
+ -- context(new_latelua(function() extend(name,tag) end))
+ ctx_latelua(function() extend(name,tag) end)
end
local function setpagestaterealpageno(name,tag)
@@ -304,7 +320,7 @@ implement {
implement {
name = "pagestaterealpage",
- actions = pagestaterealpage,
+ actions = { realpage, context },
arguments = "2 strings",
}
@@ -313,3 +329,9 @@ implement {
actions = setpagestaterealpageno,
arguments = "2 strings",
}
+
+implement {
+ name = "pagestaterealpageorder",
+ actions = { realpageorder, context },
+ arguments = { "string", "integer" }
+}
diff --git a/tex/context/base/mkiv/core-dat.mkiv b/tex/context/base/mkiv/core-dat.mkiv
index 3bb923af4..9f4344b99 100644
--- a/tex/context/base/mkiv/core-dat.mkiv
+++ b/tex/context/base/mkiv/core-dat.mkiv
@@ -73,9 +73,18 @@
{\clf_datasetvariable{#1}{#2}{#3}}
\installcorenamespace{pagestate}
+\installcorenamespace{pagestatecounter}
\installcommandhandler \??pagestate {pagestate} \??pagestate
+\def\syst_pagestates_allocate
+ {\expandafter\newcount\csname\??pagestatecounter\currentpagestate\endcsname
+ \expandafter\let\expandafter\c_syst_pagestate\csname\??pagestatecounter\currentpagestate\endcsname}
+
+\appendtoks
+ \syst_pagestates_allocate
+\to \everydefinepagestate
+
\setuppagestate
[\c!delay=\v!yes]
@@ -85,17 +94,31 @@
\def\syst_pagestates_set[#1][#2]%
{\begingroup
\edef\currentpagestate{#1}%
+ \ifcsname\??pagestatecounter\currentpagestate\endcsname
+ \let\c_syst_pagestate\lastnamedcs
+ \else
+ \syst_pagestates_allocate
+ \fi
+ \global\advance\c_syst_pagestate\plusone
+ \scratchcounter\lastnamedcs
\clf_setpagestate
name {\currentpagestate}%
- tag {#2}%
+ tag {\ifsecondargument#2\else\number\c_syst_pagestate\fi}%
delay {\pagestateparameter\c!delay}%
\relax
\endgroup}
-\def\pagestaterealpage#1#2%
- {\clf_pagestaterealpage{#1}{#2}}
+\unexpanded\def\autosetpagestate#1%
+ {\secondargumentfalse\syst_pagestates_set[#1]}
+
+\def\autopagestatenumber#1{\begincsname\??pagestatecounter#1\endcsname}
+
+\def\pagestaterealpage #1#2{\clf_pagestaterealpage {#1}{#2}}
+\def\setpagestaterealpageno#1#2{\clf_setpagestaterealpageno{#1}{#2}}
+\def\pagestaterealpageorder#1#2{\clf_pagestaterealpageorder{#1}#2\relax}
-\def\setpagestaterealpageno#1#2%
- {\clf_setpagestaterealpageno{#1}{#2}}
+\def\autopagestaterealpage #1{\clf_pagestaterealpage {#1}{\number\autopagestatenumber{#1}}}
+\def\setautopagestaterealpageno#1{\clf_setpagestaterealpageno{#1}{\number\autopagestatenumber{#1}}}
+\def\autopagestaterealpageorder#1{\clf_pagestaterealpageorder{#1}\numexpr\autopagestatenumber{#1}\relax}
\protect
diff --git a/tex/context/base/mkiv/core-def.mkiv b/tex/context/base/mkiv/core-def.mkiv
index 9dbb16f5c..95f7f2577 100644
--- a/tex/context/base/mkiv/core-def.mkiv
+++ b/tex/context/base/mkiv/core-def.mkiv
@@ -39,7 +39,7 @@
% \flushcommentanchors
\flushnotes
\synchronizenotes
- \OTRSETshowstatus
+ % \OTRSETshowstatus
\registerparoptions
% \flushsyncpositions
\flushpostponednodedata
diff --git a/tex/context/base/mkiv/core-env.lua b/tex/context/base/mkiv/core-env.lua
index 0ef37a6d6..50759dd19 100644
--- a/tex/context/base/mkiv/core-env.lua
+++ b/tex/context/base/mkiv/core-env.lua
@@ -26,6 +26,7 @@ local setmetatablenewindex = table.setmetatablenewindex
local setmetatablecall = table.setmetatablecall
local createtoken = token.create
+local isdefined = tokens.isdefined
texmodes = allocate { } tex.modes = texmodes
texsystemmodes = allocate { } tex.systemmodes = texsystemmodes
@@ -40,18 +41,27 @@ local systemmodes = { }
-- we could use the built-in tex.is[count|dimen|skip|toks] here but caching
-- at the lua end is not that bad (and we need more anyway)
--- undefined: mode == 0 or cmdname = "undefined_cs"
-
-local cache = setmetatableindex(function(t,k)
- local v = createtoken(k)
- t[k] = v
- return v
-end)
+local cache = tokens.cache
-- we can have a modes cache too
-local iftrue = cache["iftrue"].mode
-local undefined = cache["*undefined*crap*"].mode -- is this ok?
+local iftrue = cache["iftrue"].mode
+
+local dimencode = cache["scratchdimen"] .command
+local countcode = cache["scratchcounter"] .command
+local tokencode = cache["scratchtoken"] .command
+local skipcode = cache["scratchskip"] .command
+local muskipcode = cache["scratchmuskip"] .command
+----- attributecode = cache["scratchattribute"].command
+
+local types = {
+ [dimencode] = "dimen",
+ [countcode] = "count",
+ [tokencode] = "token",
+ [skipcode] = "skip",
+ [muskipcode] = "muskip",
+ -- [attributecode] = "attribute",
+}
setmetatableindex(texmodes, function(t,k)
local m = modes[k]
@@ -59,16 +69,17 @@ setmetatableindex(texmodes, function(t,k)
return m()
elseif k then
local n = "mode>" .. k
- if cache[n].mode == 0 then
- return false
- else
+ if isdefined(n) then
rawset(modes,k, function() return texgetcount(n) == 1 end)
return texgetcount(n) == 1 -- 2 is prevented
+ else
+ return false
end
else
return false
end
end)
+
setmetatablenewindex(texmodes, function(t,k)
report_mode("you cannot set the %s named %a this way","mode",k)
end)
@@ -79,11 +90,11 @@ setmetatableindex(texsystemmodes, function(t,k)
return m()
else
local n = "mode>*" .. k
- if cache[n].mode == 0 then
- return false
- else
+ if isdefined(n) then
rawset(systemmodes,k,function() return texgetcount(n) == 1 end)
return texgetcount(n) == 1 -- 2 is prevented
+ else
+ return false
end
end
end)
@@ -112,31 +123,7 @@ setmetatablenewindex(texifs, function(t,k)
-- just ignore
end)
-setmetatableindex(texisdefined, function(t,k)
- return k and cache[k].mode ~= 0
-end)
-setmetatablecall(texisdefined, function(t,k)
- return k and cache[k].mode ~= 0
-end)
-setmetatablenewindex(texisdefined, function(t,k)
- -- just ignore
-end)
-
-local dimencode = cache["scratchdimen"] .command
-local countcode = cache["scratchcounter"] .command
-local tokencode = cache["scratchtoken"] .command
-local skipcode = cache["scratchskip"] .command
-local muskipcode = cache["scratchmuskip"] .command
----- attributecode = cache["scratchattribute"].command
-
-local types = {
- [dimencode] = "dimen",
- [countcode] = "count",
- [tokencode] = "token",
- [skipcode] = "skip",
- [muskipcode] = "muskip",
- -- [attributecode] = "attribute",
-}
+tex.isdefined = isdefined
function tex.isdimen(name)
local hit = cache[name]
diff --git a/tex/context/base/mkiv/core-env.mkiv b/tex/context/base/mkiv/core-env.mkiv
index c93350db0..758ee126d 100644
--- a/tex/context/base/mkiv/core-env.mkiv
+++ b/tex/context/base/mkiv/core-env.mkiv
@@ -68,6 +68,14 @@
{\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
\lastnamedcs\disabledmode}
+\unexpanded\def\globalsetmode#1%
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \global\lastnamedcs\enabledmode}
+
+\unexpanded\def\globalresetmode#1%
+ {\ifcsname\??mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \global\lastnamedcs\disabledmode}
+
\unexpanded\def\newsystemmode#1%
{\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi}
@@ -79,6 +87,14 @@
{\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
\lastnamedcs\disabledmode}
+\unexpanded\def\globalsetsystemmode#1%
+ {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+ \global\lastnamedcs\enabledmode}
+
+\unexpanded\def\globalresetsystemmode#1%
+ {\ifcsname\??mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+ \global\lastnamedcs\disabledmode}
+
% \def\dosetsystemmode#1%
% {\csname\??mode\systemmodeprefix#1\endcsname\enabledmode}
%
@@ -87,16 +103,18 @@
% demo: trialtypesetting is a systemmode as well as an if
-\newsystemmode{trialtypesetting} % the name of \@@trialtypesetting might change (also at the lua end)
+\newsystemmode{trialtypesetting}
-\expandafter\let\expandafter\@@trialtypesetting\csname\??mode\systemmodeprefix trialtypesetting\endcsname % private !
+\expandafter\let\csname\??mode\systemmodeprefix trialtypesetting\endcsname\trialtypesettingstate
\appendtoks
- \@@trialtypesetting\enabledmode
+ \trialtypesettingstate\enabledmode
+ \luacopyinputnodes\plusone
\to \everysettrialtypesetting
\appendtoks
- \@@trialtypesetting\disabledmode
+ \trialtypesettingstate\disabledmode
+ \luacopyinputnodes\zerocount
\to \everyresettrialtypesetting
% user ones
@@ -661,6 +679,24 @@
\dodoglobal\undefinevalue{\??setup:#1}%
\fi}
+% \unexpanded\def\resetsetups[#1]% see x-fo for usage
+% {\dodoglobal\expandafter\let\csname\??setup
+% \ifgridsnapping\ifcsname\??setup\v!grid:#1\endcsname\v!grid\fi
+% :#1\endcsname\undefined}
+
+\unexpanded\def\copysetups
+ {\dodoubleargument\syst_setups_copy}
+
+% \def\syst_setups_copy[#1][#2]%
+% {\ifcsname\??setup:#2\endcsname
+% \expandafter\let\csname\??setup:#1\expandafter\endcsname\csname\??setup:#2\endcsname
+% \fi}
+
+\def\syst_setups_copy[#1][#2]%
+ {\ifcsname\??setup:#2\endcsname
+ \expandafter\let\csname\??setup:#1\expandafter\endcsname\lastnamedcs
+ \fi}
+
\unexpanded\def\showsetupsdefinition[#1]%
{\showvalue{\??setup:#1}} % temp hack for debugging
@@ -777,7 +813,7 @@
%{\edef\m_syst_string_one{\csname\??variables\ifcsname\??variables#1:#2\endcsname#1:#2\else:\fi\endcsname}%
{\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}%
\ifx\m_syst_string_one\empty
- \expandafter\firstoffourarguments
+ \expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
diff --git a/tex/context/base/mkiv/core-lmt.lua b/tex/context/base/mkiv/core-lmt.lua
new file mode 100644
index 000000000..700ce4721
--- /dev/null
+++ b/tex/context/base/mkiv/core-lmt.lua
@@ -0,0 +1,34 @@
+if not modules then modules = { } end modules ['core-lmt'] = {
+ version = 1.001,
+ comment = "companion to core-lmt.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local implement = interfaces.implement
+local scankeyword = tokens.scanners.keyword
+
+local settextdir = tex.settextdir
+local setlinedir = tex.setlinedir
+local setpardir = tex.setpardir
+local setboxdir = tex.setboxdir
+
+local function scandir(what)
+ if scankeyword("tlt") then
+ what(0)
+ elseif scankeyword("trt") then
+ what(1)
+ -- elseif scankeyword("rtt") then
+ -- what(2)
+ -- elseif scankeyword("ltl") then
+ -- what(3)
+ else
+ what(0)
+ end
+end
+
+implement { name = "textdir", public = true, protected = true, actions = function() scandir(settextdir) end }
+implement { name = "linedir", public = true, protected = true, actions = function() scandir(setlinedir) end }
+implement { name = "pardir", public = true, protected = true, actions = function() scandir(setpardir) end }
+implement { name = "boxdir", public = true, protected = true, actions = function() scandir(setboxdir) end }
diff --git a/tex/context/base/mkiv/core-lmt.mkiv b/tex/context/base/mkiv/core-lmt.mkiv
new file mode 100644
index 000000000..eda667969
--- /dev/null
+++ b/tex/context/base/mkiv/core-lmt.mkiv
@@ -0,0 +1,32 @@
+%D \module
+%D [ file=core-lmt,
+%D version=2010.08.2,
+%D title=\CONTEXT\ System 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
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\ifcase\contextlmtxmode\expandafter\endinput\fi
+
+\writestatus{loading}{ConTeXt System Macros / Primitives}
+
+\ifdefined\textdir \else
+ \registerctxluafile{core-lmt}{}
+\fi
+
+\unprotect
+
+% nothing yet
+
+\protect \endinput
+
+% \starttext
+% abc{\textdir TRTdef}ghi
+% abc{\textdir trtdef}ghi
+% \boxdirection0=1
+% \stoptext
diff --git a/tex/context/base/mkiv/core-sys.lua b/tex/context/base/mkiv/core-sys.lua
index 26229235b..4078ab8a8 100644
--- a/tex/context/base/mkiv/core-sys.lua
+++ b/tex/context/base/mkiv/core-sys.lua
@@ -73,13 +73,13 @@ implement { name = "outputfilename", actions = function() context(environme
statistics.register("result saved in file", function()
-- suffix will be fetched from backend
local outputfilename = environment.outputfilename or environment.jobname or tex.jobname or "<unset>"
- if (tex.pdfoutput or tex.outputmode) > 0 then
+ -- if (tex.pdfoutput or tex.outputmode) > 0 then
return format("%s.%s, compresslevel %s, objectcompresslevel %s",outputfilename,"pdf",
lpdf.getcompression()
)
- else
- return format("%s.%s",outputfilename,"dvi") -- hard to imagine
- end
+ -- else
+ -- return format("%s.%s",outputfilename,"dvi") -- hard to imagine
+ -- end
end)
implement {
diff --git a/tex/context/base/mkiv/core-two.lua b/tex/context/base/mkiv/core-two.lua
index 1e59004be..3ab2112b9 100644
--- a/tex/context/base/mkiv/core-two.lua
+++ b/tex/context/base/mkiv/core-two.lua
@@ -32,7 +32,7 @@ end
job.register('job.passes.collected', tobesaved, initializer, nil)
-local function allocate(id)
+local function define(id)
local p = tobesaved[id]
if not p then
p = { }
@@ -41,10 +41,8 @@ local function allocate(id)
return p
end
-jobpasses.define = allocate
-
-function jobpasses.save(id,str,index)
- local jti = allocate(id)
+local function save(id,str,index)
+ local jti = define(id)
if index then
jti[index] = str
else
@@ -52,30 +50,30 @@ function jobpasses.save(id,str,index)
end
end
-function jobpasses.savetagged(id,tag,str)
- local jti = allocate(id)
+local function savetagged(id,tag,str)
+ local jti = define(id)
jti[tag] = str
end
-function jobpasses.getdata(id,index,default)
+local function getdata(id,index,default)
local jti = collected[id]
local value = jti and jti[index]
return value ~= "" and value or default or ""
end
-function jobpasses.getfield(id,index,tag,default)
+local function getfield(id,index,tag,default)
local jti = collected[id]
jti = jti and jti[index]
local value = jti and jti[tag]
return value ~= "" and value or default or ""
end
-function jobpasses.getcollected(id)
+local function getcollected(id)
return collected[id] or { }
end
-function jobpasses.gettobesaved(id)
- return allocate(id)
+local function gettobesaved(id)
+ return define(id)
end
local function get(id)
@@ -87,23 +85,17 @@ end
local function first(id)
local jti = collected[id]
- if jti and #jti > 0 then
- return jti[1]
- end
+ return jti and jti[1]
end
local function last(id)
local jti = collected[id]
- if jti and #jti > 0 then
- return jti[#jti]
- end
+ return jti and jti[#jti]
end
local function find(id,n)
local jti = collected[id]
- if jti and jti[n] then
- return jti[n]
- end
+ return jti and jti[n] or nil
end
local function count(id)
@@ -132,44 +124,49 @@ end
local check = first
---
-
-jobpasses.get = get
-jobpasses.first = first
-jobpasses.last = last
-jobpasses.find = find
-jobpasses.list = list
-jobpasses.count = count
-jobpasses.check = check
-jobpasses.inlist = inlist
+jobpasses.define = define
+jobpasses.save = save
+jobpasses.savetagged = savetagged
+jobpasses.getdata = getdata
+jobpasses.getfield = getfield
+jobpasses.getcollected = getcollected
+jobpasses.gettobesaved = gettobesaved
+jobpasses.get = get
+jobpasses.first = first
+jobpasses.last = last
+jobpasses.find = find
+jobpasses.list = list
+jobpasses.count = count
+jobpasses.check = check
+jobpasses.inlist = inlist
-- interface
local implement = interfaces.implement
-implement { name = "gettwopassdata", actions = { get , context }, arguments = "string" }
+implement { name = "gettwopassdata", actions = { get, context }, arguments = "string" }
implement { name = "getfirsttwopassdata",actions = { first, context }, arguments = "string" }
-implement { name = "getlasttwopassdata", actions = { last , context }, arguments = "string" }
-implement { name = "findtwopassdata", actions = { find , context }, arguments = "2 strings" }
-implement { name = "gettwopassdatalist", actions = { list , context }, arguments = "string" }
+implement { name = "getlasttwopassdata", actions = { last, context }, arguments = "string" }
+implement { name = "findtwopassdata", actions = { find, context }, arguments = "2 strings" }
+implement { name = "gettwopassdatalist", actions = { list, context }, arguments = "string" }
implement { name = "counttwopassdata", actions = { count, context }, arguments = "string" }
implement { name = "checktwopassdata", actions = { check, context }, arguments = "string" }
implement {
name = "definetwopasslist",
- actions = jobpasses.define,
+ actions = define,
arguments = "string"
}
implement {
name = "savetwopassdata",
- actions = jobpasses.save,
+ actions = save,
arguments = "2 strings",
}
implement {
name = "savetaggedtwopassdata",
- actions = jobpasses.savetagged,
+ actions = savetagged,
arguments = "3 strings",
}
@@ -178,3 +175,23 @@ implement {
actions = { inlist, commands.doifelse },
arguments = "2 strings",
}
+
+-- local ctx_latelua = context.latelua
+
+-- implement {
+-- name = "lazysavetwopassdata",
+-- arguments = "3 strings",
+-- public = true,
+-- actions = function(a,b,c)
+-- ctx_latelua(function() save(a,c) end)
+-- end,
+-- }
+
+-- implement {
+-- name = "lazysavetaggedtwopassdata",
+-- arguments = "3 strings",
+-- public = true,
+-- actions = function(a,b,c)
+-- ctx_latelua(function() savetagged(a,b,c) end)
+-- end,
+-- }
diff --git a/tex/context/base/mkiv/core-two.mkiv b/tex/context/base/mkiv/core-two.mkiv
index f83d63042..aae4902bc 100644
--- a/tex/context/base/mkiv/core-two.mkiv
+++ b/tex/context/base/mkiv/core-two.mkiv
@@ -74,10 +74,10 @@
\registerctxluafile{core-two}{}
\def\immediatesavetwopassdata #1#2#3{\normalexpanded{\noexpand\clf_savetwopassdata{#1}{#3}}}
-\def\savetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatecommand{savetwopassdata('#1',"#3")}}}
-\def\lazysavetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatecommand{savetwopassdata('#1',"#3")}}}
-\def\savetaggedtwopassdata #1#2#3#4{\normalexpanded{\noexpand\clf_savetaggedtwopassdata{#1}{#3}{#4}}}
-\def\lazysavetaggedtwopassdata#1#2#3#4{\normalexpanded{\noexpand\ctxlatecommand{savetaggedtwopassdata('#1','#3',"#4")}}}
+\def \lazysavetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatecommand{savetwopassdata("#1","#3")}}}
+\let \savetwopassdata \lazysavetwopassdata
+\def \savetaggedtwopassdata#1#2#3#4{\normalexpanded{\noexpand\clf_savetaggedtwopassdata{#1}{#3}{#4}}}
+\def\lazysavetaggedtwopassdata#1#2#3#4{\normalexpanded{\noexpand\ctxlatecommand{savetaggedtwopassdata("#1",'#3',"#4")}}}
% temp hack: needs a proper \starteverytimeluacode
diff --git a/tex/context/base/mkiv/core-uti.lua b/tex/context/base/mkiv/core-uti.lua
index b281b81a4..cd867db1b 100644
--- a/tex/context/base/mkiv/core-uti.lua
+++ b/tex/context/base/mkiv/core-uti.lua
@@ -43,7 +43,7 @@ local report_passes = logs.reporter("job","passes")
job = job or { }
local job = job
-job.version = 1.30
+job.version = 1.31
job.packversion = 1.02
-- some day we will implement loading of other jobs and then we need
@@ -195,6 +195,7 @@ end
local packlist = {
"numbers",
+ "ownnumbers",
"metadata",
"sectiondata",
"prefixdata",
@@ -209,6 +210,7 @@ local packlist = {
local skiplist = {
"datasets",
"userdata",
+ "positions",
}
-- not ok as we can have arbitrary keys in userdata and dataset so some day we
@@ -398,7 +400,7 @@ function statistics.callbacks()
local c_internal = status.callbacks or 0
local c_file = status.indirect_callbacks or 0
local c_direct = status.direct_callbacks or 0
- local c_late = status.late_callbacks or 0
+ local c_late = backends.noflatelua() or 0
local c_function = status.function_callbacks or 0
local c_total = c_internal + c_file + c_direct + c_late + c_function
local n_pages = texgetcount('realpageno') - 1
@@ -430,6 +432,7 @@ end)
-- local used_wood_factor = watts_per_core * kg_per_watt_per_second / speedup_by_other_engine
-- local used_wood_factor = (50 / 15000000) / 1.2
+
function statistics.formatruntime(runtime)
if not environment.initex then -- else error when testing as not counters yet
-- stoptiming(statistics) -- to be sure
@@ -438,19 +441,15 @@ function statistics.formatruntime(runtime)
if pages > shipped then
pages = shipped
end
+ runtime = tonumber(runtime)
if shipped > 0 or pages > 0 then
- runtime = tonumber(runtime)
local persecond = (runtime > 0) and (shipped/runtime) or pages
- if pages == 0 then pages = shipped end
- -- if TEXENGINE == "luajittex" then
- -- local saved = watts_per_core * runtime * kg_per_watt_per_second / speedup_by_other_engine
- -- local saved = used_wood_factor * runtime
- -- return format("%s seconds, %i processed pages, %i shipped pages, %.3f pages/second, %f mg tree saved by using luajittex",runtime,pages,shipped,persecond,saved*1000*1000)
- -- else
- return format("%s seconds, %i processed pages, %i shipped pages, %.3f pages/second",runtime,pages,shipped,persecond)
- -- end
+ if pages == 0 then
+ pages = shipped
+ end
+ return format("%0.3f seconds, %i processed pages, %i shipped pages, %.3f pages/second",runtime,pages,shipped,persecond)
else
- return format("%s seconds",runtime)
+ return format("%0.3f seconds",runtime)
end
end
end
diff --git a/tex/context/base/mkiv/data-aux.lua b/tex/context/base/mkiv/data-aux.lua
index 1e020d1e8..c57f16d2c 100644
--- a/tex/context/base/mkiv/data-aux.lua
+++ b/tex/context/base/mkiv/data-aux.lua
@@ -50,7 +50,7 @@ function resolvers.updatescript(oldname,newname) -- oldname -> own.name, not per
local newdata = io.loaddata(newscript)
if newdata then
if trace_locating then
- report_scripts("old script content replaced by new content")
+ report_scripts("old script content replaced by new content: %s",oldscript)
end
io.savedata(oldscript,newdata)
break
diff --git a/tex/context/base/mkiv/data-pre.lua b/tex/context/base/mkiv/data-pre.lua
index 70b2e7354..5e3020b70 100644
--- a/tex/context/base/mkiv/data-pre.lua
+++ b/tex/context/base/mkiv/data-pre.lua
@@ -6,6 +6,25 @@ if not modules then modules = { } end modules ['data-pre'] = {
license = "see context related readme files"
}
+-- filename : only the basename, including suffix (file:)
+-- pathname : the pathpart (path:)
+-- locate : lookup in database (full: kpse: loc:)
+-- home : home path
+-- jobpath : job path
+-- relative : relative path ./ ../ ../.. (rel:)
+-- auto : relatove or lookup
+-- toppath : topmost path in input stack
+-- selfautodir : rather tex specific
+-- selfautoloc : rather tex specific
+-- selfautoparent : rather tex specific
+-- environment : expansion of variable (env:)
+--
+-- nodename : computer name
+-- machine : private, when set
+-- sysname : operating system name
+-- version : operating system version
+-- release : operating system release
+
local resolvers = resolvers
local prefixes = resolvers.prefixes
@@ -140,7 +159,6 @@ resolvers.setdynamic("toppath")
resolvers.setdynamic("jobpath")
-- for a while (obsolete):
-
-prefixes.jobfile = prefixes.jobpath
-
-resolvers.setdynamic("jobfile")
+--
+-- prefixes.jobfile = prefixes.jobpath
+-- resolvers.setdynamic("jobfile")
diff --git a/tex/context/base/mkiv/data-res.lua b/tex/context/base/mkiv/data-res.lua
index 9fb33f88d..0c2735fc2 100644
--- a/tex/context/base/mkiv/data-res.lua
+++ b/tex/context/base/mkiv/data-res.lua
@@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local gsub, find, lower, upper, match, gmatch = string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
-local concat, insert, remove, sortedkeys, sortedhash = table.concat, table.insert, table.remove, table.sortedkeys, table.sortedhash
+local concat, insert, remove = table.concat, table.insert, table.remove
local next, type, rawget = next, type, rawget
local os = os
@@ -1875,7 +1875,7 @@ function resolvers.booleanvariable(str,default)
end
function resolvers.dowithfilesintree(pattern,handle,before,after) -- will move, can be a nice iterator instead
- local hashes = instance.hashes
+ local hashes = instance.hashes
for i=1,#hashes do
local hash = hashes[i]
local blobtype = hash.type
@@ -1903,7 +1903,7 @@ function resolvers.dowithfilesintree(pattern,handle,before,after) -- will move,
end
end
if after then
- after(blobtype,blobpath,pattern,total,checked,done)
+ after(blobtype,blobpath,pattern,checked,done)
end
end
end
diff --git a/tex/context/base/mkiv/data-tex.lua b/tex/context/base/mkiv/data-tex.lua
index 2d2c9b24d..8f978a204 100644
--- a/tex/context/base/mkiv/data-tex.lua
+++ b/tex/context/base/mkiv/data-tex.lua
@@ -149,19 +149,19 @@ function helpers.textopener(tag,filename,filehandle,coding)
currentline = currentline + 1
-- self.currentline = currentline
local content = lines[currentline]
- if not content then
- return nil
- elseif content == "" then
+ if content == "" then
return ""
-- elseif content == ctrl_d or ctrl_z then
-- return nil -- we need this as \endinput does not work in prints
- else
+ elseif content then
local runner = textlineactions.runner
if runner then
return runner(content,filename,currentline,noflines,coding) or content
else
return content
end
+ else
+ return nil
end
end
end
diff --git a/tex/context/base/mkiv/data-tre.lua b/tex/context/base/mkiv/data-tre.lua
index 4388731f9..c4d43e3eb 100644
--- a/tex/context/base/mkiv/data-tre.lua
+++ b/tex/context/base/mkiv/data-tre.lua
@@ -100,11 +100,10 @@ end
function resolvers.hashers.tree(specification)
local name = specification.filename
- -- if trace_locating then
+ if trace_locating then
report_trees("analyzing %a",name)
- -- end
+ end
resolvers.methodhandler("hashers",name)
-
resolvers.generators.file(specification)
end
diff --git a/tex/context/base/mkiv/data-use.lua b/tex/context/base/mkiv/data-use.lua
index ff25c803a..5985a2eac 100644
--- a/tex/context/base/mkiv/data-use.lua
+++ b/tex/context/base/mkiv/data-use.lua
@@ -69,7 +69,11 @@ function statistics.savefmtstatus(texname,formatbanner,sourcefile,kind,banner) -
}
io.savedata(luvname,table.serialize(luvdata,true))
lua.registerfinalizer(function()
- logs.report("format banner","%s",banner)
+ if jit then
+ logs.report("format banner","%s lua: %s jit",banner,LUAVERSION)
+ else
+ logs.report("format banner","%s lua: %s",banner,LUAVERSION)
+ end
logs.newline()
end)
end
diff --git a/tex/context/base/mkiv/data-zip.lua b/tex/context/base/mkiv/data-zip.lua
index 32666bef2..6f20b4a9d 100644
--- a/tex/context/base/mkiv/data-zip.lua
+++ b/tex/context/base/mkiv/data-zip.lua
@@ -31,11 +31,11 @@ local resolvers = resolvers
zip = zip or { }
local zip = zip
-zip.archives = zip.archives or { }
-local archives = zip.archives
+local archives = zip.archives or { }
+zip.archives = archives
-zip.registeredfiles = zip.registeredfiles or { }
-local registeredfiles = zip.registeredfiles
+local registeredfiles = zip.registeredfiles or { }
+zip.registeredfiles = registeredfiles
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
@@ -108,7 +108,7 @@ function resolvers.finders.zip(specification)
end
local dfile = zfile:open(queryname)
if dfile then
- dfile = zfile:close()
+ dfile:close()
if trace_locating then
report_zip("finder: file %a found",queryname)
end
diff --git a/tex/context/base/mkiv/driv-ini.lua b/tex/context/base/mkiv/driv-ini.lua
new file mode 100644
index 000000000..e16327f27
--- /dev/null
+++ b/tex/context/base/mkiv/driv-ini.lua
@@ -0,0 +1,194 @@
+if not modules then modules = { } end modules ['driv-ini'] = {
+ version = 1.001,
+ comment = "companion to driv-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type = type
+local addsuffix = file.addsuffix
+
+local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local report = logs.reporter("drivers")
+
+local instances = { }
+local helpers = { }
+local prepared = { }
+local wrappedup = { }
+local currentdriver = "default"
+
+local prepare = nil
+local convert = nil
+local wrapup = nil
+local outputfilename = nil
+
+drivers = drivers or {
+ instances = instances,
+ helpers = helpers,
+ lmtxversion = 0.10,
+}
+
+local dummy = function() end
+
+local defaulthandlers = {
+ prepare = dummy,
+ initialize = dummy,
+ finalize = dummy,
+ updatefontstate = dummy,
+ wrapup = dummy,
+ convert = dummy,
+ outputfilename = dummy,
+}
+
+function drivers.install(specification)
+ local name = specification.name
+ if not name then
+ report("missing driver name")
+ return
+ end
+ local actions = specification.actions
+ if not actions then
+ report("no actions for driver %a",name)
+ return
+ end
+ local flushers = specification.flushers
+ if not flushers then
+ report("no flushers for driver %a",name)
+ return
+ end
+ setmetatableindex(actions,defaulthandlers)
+ instances[name] = specification
+end
+
+function drivers.convert(boxnumber)
+ callbacks.functions.start_page_number()
+ starttiming(drivers)
+ convert(boxnumber)
+ stoptiming(drivers)
+ callbacks.functions.stop_page_number()
+end
+
+function drivers.outputfilename()
+ return outputfilename()
+end
+
+
+luatex.wrapup(function()
+ if not wrappedup[currentdriver] then
+ starttiming(drivers)
+ wrapup()
+ stoptiming(drivers)
+ wrappedup[currentdriver] = true
+ end
+end)
+
+function drivers.enable(name)
+ currentdriver = name or "default"
+ local actions = instances[currentdriver].actions
+ prepare = actions.prepare
+ wrapup = actions.wrapup
+ convert = actions.convert
+ outputfilename = actions.outputfilename
+ --
+ if prepare and not prepared[currentdriver] then
+ starttiming(drivers)
+ prepare()
+ stoptiming(drivers)
+ prepared[currentdriver] = true
+ end
+end
+
+statistics.register("driver time",function()
+ return statistics.elapsedseconds(drivers)
+end)
+
+interfaces.implement {
+ name = "shipoutpage",
+ arguments = "integer",
+ actions = drivers.convert,
+}
+
+interfaces.implement {
+ name = "enabledriver",
+ arguments = "string",
+ actions = drivers.enable,
+}
+
+-- The default driver:
+
+do
+
+ local filename = nil
+
+ drivers.install {
+ name = "default",
+ actions = {
+ convert = tex.shipout,
+ outputfilename = function()
+ if not filename then
+ filename = addsuffix(tex.jobname,"pdf")
+ end
+ return filename
+ end,
+ },
+ flushers = {
+ -- we always need this entry
+ },
+ }
+
+end
+
+setmetatableindex(instances,function() return instances.default end)
+
+-- for now:
+
+drivers.enable("default")
+
+-- helpers
+
+local s_matrix_0 = "1 0 0 1"
+local f_matrix_2 = formatters["%.6F 0 0 %.6F"]
+local f_matrix_4 = formatters["%.6F %.6F %.6F %.6F"]
+
+directives.register("pdf.stripzeros",function()
+ f_matrix_2 = formatters["%.6N 0 0 %.6N"]
+ f_matrix_4 = formatters["%.6N %.6N %.6N %.6N"]
+end)
+
+function helpers.tomatrix(rx,sx,sy,ry,tx,ty) -- todo: tx ty
+ if type(rx) == "string" then
+ return rx
+ else
+ if not rx then
+ rx = 1
+ elseif rx == 0 then
+ rx = 0.0001
+ end
+ if not ry then
+ ry = 1
+ elseif ry == 0 then
+ ry = 0.0001
+ end
+ if not sx then
+ sx = 0
+ end
+ if not sy then
+ sy = 0
+ end
+ if sx == 0 and sy == 0 then
+ if rx == 1 and ry == 1 then
+ return s_matrix_0
+ else
+ return f_matrix_2(rx,ry)
+ end
+ else
+ return f_matrix_4(rx,sx,sy,ry)
+ end
+ end
+end
diff --git a/tex/context/base/mkiv/driv-ini.mkiv b/tex/context/base/mkiv/driv-ini.mkiv
new file mode 100644
index 000000000..95b6c88a7
--- /dev/null
+++ b/tex/context/base/mkiv/driv-ini.mkiv
@@ -0,0 +1,25 @@
+%D \module
+%D [ file=driv-ini,
+%D version=2018.07.26,
+%D title=\CONTEXT\ Driver Macros,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Driver Macros / Initialization}
+
+\registerctxluafile{driv-ini}{}
+
+\unprotect
+
+\def\page_shipout_box#1%
+ {\clf_shipoutpage#1\relax
+ \setbox#1\emptybox
+ \global\deadcycles\zerocount}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/export-example.css b/tex/context/base/mkiv/export-example.css
index 812873afc..c39f0bec6 100644
--- a/tex/context/base/mkiv/export-example.css
+++ b/tex/context/base/mkiv/export-example.css
@@ -34,8 +34,9 @@
@namespace context url('http://www.pragma-ade.com/context/export') ;
-/* ignore : mixed */
-/* metadata: display */
+/* ignore : mixed */
+/* metadata : display */
+/* extradata: display */
ignore,
context|div.ignore {
@@ -57,6 +58,11 @@ context|div.xmetavariable {
display : none ;
}
+extradata,
+context|div.extradata {
+ display : none ;
+}
+
/* document : display */
document:before,
@@ -679,6 +685,7 @@ context|div.combinationcaption {
/* listcontent : mixed */
/* listdata : mixed */
/* listpage : mixed */
+/* listtext : inline */
list,
context|div.list {
@@ -758,6 +765,11 @@ context|div.listpage {
display : none ;
}
+listtext,
+context|div.listtext {
+ display : inline ;
+}
+
/* delimitedblock : display */
/* delimited : inline */
/* delimitedsymbol : inline */
@@ -1024,6 +1036,20 @@ context|div.math-display {
margin : 1ex 0ex 1em 3em ;
}
+/* publication : inline */
+/* pubfld : inline */
+
+publication,
+context|div.publication {
+ display : inline ;
+}
+
+pubfld[detail="title"],
+context|div.pubfld.title {
+ display : inline ;
+ font-weight : italic ;
+}
+
/* quantity : inline */
/* unit : inline */
/* number : inline */
@@ -1097,6 +1123,13 @@ context|div.comment {
font-family : "DejaVu Sans Mono", "Lucida Console", monospace ;
}
+/* blocks */
+
+block,
+context|div.block {
+ display : block ;
+}
+
/* special */
c,
diff --git a/tex/context/base/mkiv/file-job.lua b/tex/context/base/mkiv/file-job.lua
index dbf6da9b4..486aee63a 100644
--- a/tex/context/base/mkiv/file-job.lua
+++ b/tex/context/base/mkiv/file-job.lua
@@ -386,7 +386,6 @@ local function starttext()
if trace_jobfiles then
report_jobfiles("starting text")
end
- -- registerfileinfo[begin]jobfilename
context.dostarttext()
end
textlevel = textlevel + 1
@@ -406,8 +405,6 @@ local function stoptext()
report_jobfiles("stopping text")
end
context.dostoptext()
- -- registerfileinfo[end]jobfilename
- context.finalend()
stopped = true
end
end
diff --git a/tex/context/base/mkiv/file-job.mkvi b/tex/context/base/mkiv/file-job.mkvi
index e1ea405c0..a46e519c0 100644
--- a/tex/context/base/mkiv/file-job.mkvi
+++ b/tex/context/base/mkiv/file-job.mkvi
@@ -312,6 +312,12 @@
{\documentvariable\c!after
\stoptext}
+\unexpanded\def\doifelsedocumentvariable#name{\doifelsesomething{\documentvariable{#name}}}
+\unexpanded\def\doifdocumentvariable #name{\doifsomething {\documentvariable{#name}}}
+\unexpanded\def\doifnotdocumentvariable #name{\doifnot {\documentvariable{#name}}}
+
+\let\doifdocumentvariableelse\doifelsedocumentvariable
+
\def\documentvariable#name%
{\getvariable\s!document{#name}}
@@ -347,12 +353,15 @@
% Bonus:
-\installcorenamespace{samplefile}
+% \installcorenamespace{samplefile}
+%
+% \unexpanded\def\samplefile#1%
+% {\ifcsname\??samplefile#1\endcsname \else
+% \setxvalue{\??samplefile#1}{\cldloadfile{#1}}%
+% \fi
+% \lastnamedcs}
\unexpanded\def\samplefile#1%
- {\ifcsname\??samplefile#1\endcsname \else
- \setxvalue{\??samplefile#1}{\cldloadfile{#1}}%
- \fi
- \lastnamedcs}
+ {\clf_samplefile{#1}}
\protect \endinput
diff --git a/tex/context/base/mkiv/file-mod.mkvi b/tex/context/base/mkiv/file-mod.mkvi
index a2a3b7793..a06770e24 100644
--- a/tex/context/base/mkiv/file-mod.mkvi
+++ b/tex/context/base/mkiv/file-mod.mkvi
@@ -36,9 +36,9 @@
\let\usetexmodule\usemodules
\def\strc_modules_use[#category][#name][#parameters]% category=t|m|x|p|...
- {\pushmacro\currentmodule
- \pushmacro\currentmodulecategory
- \pushmacro\currentmoduleparameters
+ {\push_macro_currentmodule
+ \push_macro_currentmodulecategory
+ \push_macro_currentmoduleparameters
\ifthirdargument
\edef\currentmodulecategory {#category}%
\edef\currentmodule {#name}%
@@ -57,9 +57,9 @@
\let \currentmoduleparameters\empty
\fi\fi
\processcommacommand[\currentmodule]{\strc_modules_use_indeed\currentmodulecategory}%
- \popmacro\currentmoduleparameters
- \popmacro\currentmodulecategory
- \popmacro\currentmodule}
+ \pop_macro_currentmoduleparameters
+ \pop_macro_currentmodulecategory
+ \pop_macro_currentmodule}
\def\strc_modules_use_indeed#category#name%
{\ifx\currentmoduleparameters\empty\else
@@ -70,20 +70,24 @@
\installcorenamespace{module}
-\let\currentmoduleparameters\empty
\let\currentmodule \s!unknown
+\let\currentmodulecategory \empty
+\let\currentmoduleparameters\empty
-\newcount \c_syst_modules_nesting
+\installmacrostack\currentmodule
+\installmacrostack\currentmodulecategory
+\installmacrostack\currentmoduleparameters
-\newtoks\everysetupmodule
+\newcount\c_syst_modules_nesting
+\newtoks \everysetupmodule
\unexpanded\def\startmodule
{\doifelsenextoptionalcs\syst_modules_start_yes\syst_modules_start_nop}
\def\syst_modules_start_yes[#name]%
{\global\advance\c_syst_modules_nesting\plusone
- \pushmacro\currentmodule
- \pushmacro\currentmoduleparameters
+ \push_macro_currentmodule
+ \push_macro_currentmoduleparameters
\def\currentmodule{#name}}
\def\syst_modules_start_nop#name %
@@ -93,8 +97,8 @@
{\ifcase\c_syst_modules_nesting
\writestatus\m!system{module wrapping error in '\currentmodule'}%
\else
- \popmacro\currentmoduleparameters
- \popmacro\currentmodule
+ \pop_macro_currentmoduleparameters
+ \pop_macro_currentmodule
\global\advance\c_syst_modules_nesting\minusone
\fi}
@@ -203,7 +207,7 @@
{\ifcsname\??runtimeloaded#2\endcsname
% already loaded
\else
- \global\let#1\undefined
+ \glet#1\undefined
\startreadingfile
\startnointerference % \bgroup
\cleanupfeatures % better \setnormalcatcodes / test first
diff --git a/tex/context/base/mkiv/font-aux.lua b/tex/context/base/mkiv/font-aux.lua
index fcbcd6d32..4ac6278cb 100644
--- a/tex/context/base/mkiv/font-aux.lua
+++ b/tex/context/base/mkiv/font-aux.lua
@@ -185,6 +185,7 @@ end
local getters = { -- maybe better getters[format][...]
kern = {
["type1"] = afm.getkern,
+ ["type3"] = afm.getkern,
["opentype"] = otf.getkern,
},
substitution = {
diff --git a/tex/context/base/mkiv/font-cff.lua b/tex/context/base/mkiv/font-cff.lua
index 1d4f01007..46deedb5f 100644
--- a/tex/context/base/mkiv/font-cff.lua
+++ b/tex/context/base/mkiv/font-cff.lua
@@ -26,14 +26,16 @@ if not modules then modules = { } end modules ['font-cff'] = {
-- with merging subroutines and flattening, not so much with calculations.) On
-- the other hand, we can now feed back cff2 stuff.
-local next, type, tonumber = next, type, tonumber
+local next, type, tonumber, rawget = next, type, tonumber, rawget
local byte, char, gmatch = string.byte, string.char, string.gmatch
-local concat, remove = table.concat, table.remove
+local concat, remove, unpack = table.concat, table.remove, table.unpack
local floor, abs, round, ceil, min, max = math.floor, math.abs, math.round, math.ceil, math.min, math.max
local P, C, R, S, C, Cs, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct
local lpegmatch = lpeg.match
local formatters = string.formatters
local bytetable = string.bytetable
+local idiv = number.idiv
+local rshift, band, extract = bit32.rshift, bit32.band, bit32.extract
local readers = fonts.handlers.otf.readers
local streamreader = readers.streamreader
@@ -47,6 +49,21 @@ local setposition = streamreader.setposition
local getposition = streamreader.getposition
local readbytetable = streamreader.readbytetable
+directives.register("fonts.streamreader",function()
+
+ streamreader = utilities.streams
+
+ readstring = streamreader.readstring
+ readbyte = streamreader.readcardinal1
+ readushort = streamreader.readcardinal2
+ readuint = streamreader.readcardinal3
+ readulong = streamreader.readcardinal4
+ setposition = streamreader.setposition
+ getposition = streamreader.getposition
+ readbytetable = streamreader.readbytetable
+
+end)
+
local setmetatableindex = table.setmetatableindex
local trace_charstrings = false trackers.register("fonts.cff.charstrings",function(v) trace_charstrings = v end)
@@ -272,12 +289,30 @@ do
result.fontbbox = { unpack(stack,1,4) }
top = 0
end
- -- + P("\06") / function() end -- bluevalues
- -- + P("\07") / function() end -- otherblues
- -- + P("\08") / function() end -- familyblues
- -- + P("\09") / function() end -- familyotherblues
- -- + P("\10") / function() end -- strhw
- -- + P("\11") / function() end -- stdvw
+ + P("\06") / function()
+ result.bluevalues = { unpack(stack,1,top) }
+ top = 0
+ end
+ + P("\07") / function()
+ result.otherblues = { unpack(stack,1,top) }
+ top = 0
+ end
+ + P("\08") / function()
+ result.familyblues = { unpack(stack,1,top) }
+ top = 0
+ end
+ + P("\09") / function()
+ result.familyotherblues = { unpack(stack,1,top) }
+ top = 0
+ end
+ + P("\10") / function()
+ result.strhw = stack[top]
+ top = 0
+ end
+ + P("\11") / function()
+ result.strvw = stack[top]
+ top = 0
+ end
+ P("\13") / function()
result.uniqueid = stack[top]
top = 0
@@ -371,6 +406,26 @@ do
result.strokewidth = stack[top]
top = 0
end
+ + P("\09") / function()
+ result.bluescale = stack[top]
+ top = 0
+ end
+ + P("\10") / function()
+ result.bluesnap = stack[top]
+ top = 0
+ end
+ + P("\11") / function()
+ result.bluefuzz = stack[top]
+ top = 0
+ end
+ + P("\12") / function()
+ result.stemsnaph = { unpack(stack,1,top) }
+ top = 0
+ end
+ + P("\13") / function()
+ result.stemsnapv = { unpack(stack,1,top) }
+ top = 0
+ end
+ P("\20") / function()
result.syntheticbase = stack[top]
top = 0
@@ -431,52 +486,27 @@ do
-- the second variant is much faster. Not that it matters much as we don't see
-- such numbers often.
- local p_last = P("\x0F") / "0" + P("\x1F") / "1" + P("\x2F") / "2" + P("\x3F") / "3"
- + P("\x4F") / "4" + P("\x5F") / "5" + P("\x6F") / "6" + P("\x7F") / "7"
- + P("\x8F") / "8" + P("\x9F") / "9" + P("\xAF") / "" + P("\xBF") / ""
- + P("\xCF") / "" + P("\xDF") / "" + P("\xEF") / "" + R("\xF0\xFF") / ""
-
- -- local remap = { [0] =
- -- "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0.", "0E", "0E-", "0", "0-", "0",
- -- "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "0.", "0E", "0E-", "0", "0-", "0",
- -- "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "0.", "0E", "0E-", "0", "0-", "0",
- -- "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "0.", "0E", "0E-", "0", "0-", "0",
- -- "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "0.", "0E", "0E-", "0", "0-", "0",
- -- "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "0.", "0E", "0E-", "0", "0-", "0",
- -- "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "0.", "0E", "0E-", "0", "0-", "0",
- -- "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "0.", "0E", "0E-", "0", "0-", "0",
- -- "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "0.", "0E", "0E-", "0", "0-", "0",
- -- "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "0.", "0E", "0E-", "0", "0-", "0",
- -- ".0", ".1", ".2", ".3", ".4", ".5", ".6", ".7", ".8", ".9", "..", ".E", ".E-", ".", ".-", ".",
- -- "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "E.", "EE", "EE-", "E", "E-", "E",
- -- "E-0", "E-1", "E-2", "E-3", "E-4", "E-5", "E-6", "E-7", "E-8", "E-9", "E-.", "E-E", "E-E-", "E-", "E--", "E-",
- -- "-0", "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9", "-.", "-E", "-E-", "-", "--", "-",
- -- }
-
- -- local p_nibbles = Cs(((1-p_last)/byte/remap)^0+p_last)
-
- -- local p = P("\30") * p_nibbles / function(t)
- -- print(tonumber(t))
- -- end
-
local remap = {
["\x00"] = "00", ["\x01"] = "01", ["\x02"] = "02", ["\x03"] = "03", ["\x04"] = "04", ["\x05"] = "05", ["\x06"] = "06", ["\x07"] = "07", ["\x08"] = "08", ["\x09"] = "09", ["\x0A"] = "0.", ["\x0B"] = "0E", ["\x0C"] = "0E-", ["\x0D"] = "0", ["\x0E"] = "0-", ["\x0F"] = "0",
- ["\x10"] = "10", ["\x11"] = "11", ["\x12"] = "12", ["\x13"] = "13", ["\x14"] = "14", ["\x15"] = "15", ["\x16"] = "16", ["\x17"] = "17", ["\x18"] = "18", ["\x19"] = "19", ["\x1A"] = "0.", ["\x1B"] = "0E", ["\x1C"] = "0E-", ["\x1D"] = "0", ["\x1E"] = "0-", ["\x1F"] = "0",
- ["\x20"] = "20", ["\x21"] = "21", ["\x22"] = "22", ["\x23"] = "23", ["\x24"] = "24", ["\x25"] = "25", ["\x26"] = "26", ["\x27"] = "27", ["\x28"] = "28", ["\x29"] = "29", ["\x2A"] = "0.", ["\x2B"] = "0E", ["\x2C"] = "0E-", ["\x2D"] = "0", ["\x2E"] = "0-", ["\x2F"] = "0",
- ["\x30"] = "30", ["\x31"] = "31", ["\x32"] = "32", ["\x33"] = "33", ["\x34"] = "34", ["\x35"] = "35", ["\x36"] = "36", ["\x37"] = "37", ["\x38"] = "38", ["\x39"] = "39", ["\x3A"] = "0.", ["\x3B"] = "0E", ["\x3C"] = "0E-", ["\x3D"] = "0", ["\x3E"] = "0-", ["\x3F"] = "0",
- ["\x40"] = "40", ["\x41"] = "41", ["\x42"] = "42", ["\x43"] = "43", ["\x44"] = "44", ["\x45"] = "45", ["\x46"] = "46", ["\x47"] = "47", ["\x48"] = "48", ["\x49"] = "49", ["\x4A"] = "0.", ["\x4B"] = "0E", ["\x4C"] = "0E-", ["\x4D"] = "0", ["\x4E"] = "0-", ["\x4F"] = "0",
- ["\x50"] = "50", ["\x51"] = "51", ["\x52"] = "52", ["\x53"] = "53", ["\x54"] = "54", ["\x55"] = "55", ["\x56"] = "56", ["\x57"] = "57", ["\x58"] = "58", ["\x59"] = "59", ["\x5A"] = "0.", ["\x5B"] = "0E", ["\x5C"] = "0E-", ["\x5D"] = "0", ["\x5E"] = "0-", ["\x5F"] = "0",
- ["\x60"] = "60", ["\x61"] = "61", ["\x62"] = "62", ["\x63"] = "63", ["\x64"] = "64", ["\x65"] = "65", ["\x66"] = "66", ["\x67"] = "67", ["\x68"] = "68", ["\x69"] = "69", ["\x6A"] = "0.", ["\x6B"] = "0E", ["\x6C"] = "0E-", ["\x6D"] = "0", ["\x6E"] = "0-", ["\x6F"] = "0",
- ["\x70"] = "70", ["\x71"] = "71", ["\x72"] = "72", ["\x73"] = "73", ["\x74"] = "74", ["\x75"] = "75", ["\x76"] = "76", ["\x77"] = "77", ["\x78"] = "78", ["\x79"] = "79", ["\x7A"] = "0.", ["\x7B"] = "0E", ["\x7C"] = "0E-", ["\x7D"] = "0", ["\x7E"] = "0-", ["\x7F"] = "0",
- ["\x80"] = "80", ["\x81"] = "81", ["\x82"] = "82", ["\x83"] = "83", ["\x84"] = "84", ["\x85"] = "85", ["\x86"] = "86", ["\x87"] = "87", ["\x88"] = "88", ["\x89"] = "89", ["\x8A"] = "0.", ["\x8B"] = "0E", ["\x8C"] = "0E-", ["\x8D"] = "0", ["\x8E"] = "0-", ["\x8F"] = "0",
- ["\x90"] = "90", ["\x91"] = "91", ["\x92"] = "92", ["\x93"] = "93", ["\x94"] = "94", ["\x95"] = "95", ["\x96"] = "96", ["\x97"] = "97", ["\x98"] = "98", ["\x99"] = "99", ["\x9A"] = "0.", ["\x9B"] = "0E", ["\x9C"] = "0E-", ["\x9D"] = "0", ["\x9E"] = "0-", ["\x9F"] = "0",
+ ["\x10"] = "10", ["\x11"] = "11", ["\x12"] = "12", ["\x13"] = "13", ["\x14"] = "14", ["\x15"] = "15", ["\x16"] = "16", ["\x17"] = "17", ["\x18"] = "18", ["\x19"] = "19", ["\x1A"] = "1.", ["\x1B"] = "1E", ["\x1C"] = "1E-", ["\x1D"] = "1", ["\x1E"] = "1-", ["\x1F"] = "1",
+ ["\x20"] = "20", ["\x21"] = "21", ["\x22"] = "22", ["\x23"] = "23", ["\x24"] = "24", ["\x25"] = "25", ["\x26"] = "26", ["\x27"] = "27", ["\x28"] = "28", ["\x29"] = "29", ["\x2A"] = "2.", ["\x2B"] = "2E", ["\x2C"] = "2E-", ["\x2D"] = "2", ["\x2E"] = "2-", ["\x2F"] = "2",
+ ["\x30"] = "30", ["\x31"] = "31", ["\x32"] = "32", ["\x33"] = "33", ["\x34"] = "34", ["\x35"] = "35", ["\x36"] = "36", ["\x37"] = "37", ["\x38"] = "38", ["\x39"] = "39", ["\x3A"] = "3.", ["\x3B"] = "3E", ["\x3C"] = "3E-", ["\x3D"] = "3", ["\x3E"] = "3-", ["\x3F"] = "3",
+ ["\x40"] = "40", ["\x41"] = "41", ["\x42"] = "42", ["\x43"] = "43", ["\x44"] = "44", ["\x45"] = "45", ["\x46"] = "46", ["\x47"] = "47", ["\x48"] = "48", ["\x49"] = "49", ["\x4A"] = "4.", ["\x4B"] = "4E", ["\x4C"] = "4E-", ["\x4D"] = "4", ["\x4E"] = "4-", ["\x4F"] = "4",
+ ["\x50"] = "50", ["\x51"] = "51", ["\x52"] = "52", ["\x53"] = "53", ["\x54"] = "54", ["\x55"] = "55", ["\x56"] = "56", ["\x57"] = "57", ["\x58"] = "58", ["\x59"] = "59", ["\x5A"] = "5.", ["\x5B"] = "5E", ["\x5C"] = "5E-", ["\x5D"] = "5", ["\x5E"] = "5-", ["\x5F"] = "5",
+ ["\x60"] = "60", ["\x61"] = "61", ["\x62"] = "62", ["\x63"] = "63", ["\x64"] = "64", ["\x65"] = "65", ["\x66"] = "66", ["\x67"] = "67", ["\x68"] = "68", ["\x69"] = "69", ["\x6A"] = "6.", ["\x6B"] = "6E", ["\x6C"] = "6E-", ["\x6D"] = "6", ["\x6E"] = "6-", ["\x6F"] = "6",
+ ["\x70"] = "70", ["\x71"] = "71", ["\x72"] = "72", ["\x73"] = "73", ["\x74"] = "74", ["\x75"] = "75", ["\x76"] = "76", ["\x77"] = "77", ["\x78"] = "78", ["\x79"] = "79", ["\x7A"] = "7.", ["\x7B"] = "7E", ["\x7C"] = "7E-", ["\x7D"] = "7", ["\x7E"] = "7-", ["\x7F"] = "7",
+ ["\x80"] = "80", ["\x81"] = "81", ["\x82"] = "82", ["\x83"] = "83", ["\x84"] = "84", ["\x85"] = "85", ["\x86"] = "86", ["\x87"] = "87", ["\x88"] = "88", ["\x89"] = "89", ["\x8A"] = "8.", ["\x8B"] = "8E", ["\x8C"] = "8E-", ["\x8D"] = "8", ["\x8E"] = "8-", ["\x8F"] = "8",
+ ["\x90"] = "90", ["\x91"] = "91", ["\x92"] = "92", ["\x93"] = "93", ["\x94"] = "94", ["\x95"] = "95", ["\x96"] = "96", ["\x97"] = "97", ["\x98"] = "98", ["\x99"] = "99", ["\x9A"] = "9.", ["\x9B"] = "9E", ["\x9C"] = "9E-", ["\x9D"] = "9", ["\x9E"] = "9-", ["\x9F"] = "9",
["\xA0"] = ".0", ["\xA1"] = ".1", ["\xA2"] = ".2", ["\xA3"] = ".3", ["\xA4"] = ".4", ["\xA5"] = ".5", ["\xA6"] = ".6", ["\xA7"] = ".7", ["\xA8"] = ".8", ["\xA9"] = ".9", ["\xAA"] = "..", ["\xAB"] = ".E", ["\xAC"] = ".E-", ["\xAD"] = ".", ["\xAE"] = ".-", ["\xAF"] = ".",
["\xB0"] = "E0", ["\xB1"] = "E1", ["\xB2"] = "E2", ["\xB3"] = "E3", ["\xB4"] = "E4", ["\xB5"] = "E5", ["\xB6"] = "E6", ["\xB7"] = "E7", ["\xB8"] = "E8", ["\xB9"] = "E9", ["\xBA"] = "E.", ["\xBB"] = "EE", ["\xBC"] = "EE-", ["\xBD"] = "E", ["\xBE"] = "E-", ["\xBF"] = "E",
["\xC0"] = "E-0", ["\xC1"] = "E-1", ["\xC2"] = "E-2", ["\xC3"] = "E-3", ["\xC4"] = "E-4", ["\xC5"] = "E-5", ["\xC6"] = "E-6", ["\xC7"] = "E-7", ["\xC8"] = "E-8", ["\xC9"] = "E-9", ["\xCA"] = "E-.", ["\xCB"] = "E-E", ["\xCC"] = "E-E-", ["\xCD"] = "E-", ["\xCE"] = "E--", ["\xCF"] = "E-",
["\xD0"] = "-0", ["\xD1"] = "-1", ["\xD2"] = "-2", ["\xD3"] = "-3", ["\xD4"] = "-4", ["\xD5"] = "-5", ["\xD6"] = "-6", ["\xD7"] = "-7", ["\xD8"] = "-8", ["\xD9"] = "-9", ["\xDA"] = "-.", ["\xDB"] = "-E", ["\xDC"] = "-E-", ["\xDD"] = "-", ["\xDE"] = "--", ["\xDF"] = "-",
}
- local p_nibbles = P("\30") * Cs(((1-p_last)/remap)^0+p_last) / function(n)
+ local p_last = S("\x0F\x1F\x2F\x3F\x4F\x5F\x6F\x7F\x8F\x9F\xAF\xBF")
+ + R("\xF0\xFF")
+
+ local p_nibbles = P("\30") * Cs(((1-p_last)/remap)^0 * (P(1)/remap)) / function(n)
-- 0-9=digit a=. b=E c=E- d=reserved e=- f=finish
top = top + 1
stack[top] = tonumber(n) or 0
@@ -1215,7 +1245,7 @@ do
if trace_charstrings then
showstate("stem")
end
- stems = stems + top/2
+ stems = stems + idiv(top,2)
top = 0
end
@@ -1236,14 +1266,15 @@ do
if trace_charstrings then
showstate(operator == 19 and "hintmark" or "cntrmask")
end
- stems = stems + top/2
+ stems = stems + idiv(top,2)
top = 0
if stems == 0 then
-- forget about it
elseif stems <= 8 then
return 1
else
- return floor((stems+7)/8)
+ -- return floor((stems+7)/8)
+ return idiv(stems+7,8)
end
end
@@ -1290,8 +1321,9 @@ do
local function hsbw()
if version == 1 then
if trace_charstrings then
- showstate("dotsection")
+ showstate("hsbw")
end
+ -- lsb = stack[top-1]
width = stack[top]
end
top = 0
@@ -1513,88 +1545,115 @@ do
[037] = flex1,
}
- local c_endchar = char(14)
+ local chars = setmetatableindex(function (t,k)
+ local v = char(k)
+ t[k] = v
+ return v
+ end)
- local passon do
+ local c_endchar = chars[14]
- -- todo: round in blend
- -- todo: delay this hash
+ -- todo: round in blend
- local rshift = bit32.rshift
- local band = bit32.band
- local round = math.round
+ local encode = { }
- local encode = table.setmetatableindex(function(t,i)
- for i=-2048,-1130 do
- t[i] = char(28,band(rshift(i,8),0xFF),band(i,0xFF))
- end
- for i=-1131,-108 do
- local v = 0xFB00 - i - 108
- t[i] = char(band(rshift(v,8),0xFF),band(v,0xFF))
- end
- for i=-107,107 do
- t[i] = char(i + 139)
- end
- for i=108,1131 do
- local v = 0xF700 + i - 108
- t[i] = char(band(rshift(v,8),0xFF),band(v,0xFF))
- end
- for i=1132,2048 do
- t[i] = char(28,band(rshift(i,8),0xFF),band(i,0xFF))
+ -- this eventually can become a helper
+
+ setmetatableindex(encode,function(t,i)
+ for i=-2048,-1130 do
+ t[i] = char(28,band(rshift(i,8),0xFF),band(i,0xFF))
+ end
+ for i=-1131,-108 do
+ local v = 0xFB00 - i - 108
+ t[i] = char(band(rshift(v,8),0xFF),band(v,0xFF))
+ end
+ for i=-107,107 do
+ t[i] = chars[i + 139]
+ end
+ for i=108,1131 do
+ local v = 0xF700 + i - 108
+-- t[i] = char(band(rshift(v,8),0xFF),band(v,0xFF))
+ t[i] = char(extract(v,8,8),extract(v,0,8))
+ end
+ for i=1132,2048 do
+ t[i] = char(28,band(rshift(i,8),0xFF),band(i,0xFF))
+ end
+ setmetatableindex(encode,function(t,k)
+ -- 16.16-bit signed fixed value
+ local r = round(k)
+ local v = rawget(t,r)
+ if v then
+ return v
end
- return t[i]
+ local v1 = floor(k)
+ local v2 = floor((k - v1) * 0x10000)
+ return char(255,extract(v1,8,8),extract(v1,0,8),extract(v2,8,8),extract(v2,0,8))
end)
+ return t[i]
+ end)
- local function setvsindex()
- local vsindex = stack[top]
- updateregions(vsindex)
- top = top - 1
- end
+ readers.cffencoder = encode
- local function blend()
- local n = stack[top]
- top = top - 1
- if not axis then
- -- fatal error
- elseif n == 1 then
- top = top - nofregions
- local v = stack[top]
+ local function p_setvsindex()
+ local vsindex = stack[top]
+ updateregions(vsindex)
+ top = top - 1
+ end
+
+ local function p_blend()
+ -- leaves n values on stack
+ local n = stack[top]
+ top = top - 1
+ if not axis then
+ -- fatal error
+ elseif n == 1 then
+ top = top - nofregions
+ local v = stack[top]
+ for r=1,nofregions do
+ v = v + stack[top+r] * factors[r]
+ end
+ stack[top] = round(v)
+ else
+ top = top - nofregions * n
+ local d = top
+ local k = top - n
+ for i=1,n do
+ k = k + 1
+ local v = stack[k]
for r=1,nofregions do
- v = v + stack[top+r] * factors[r]
- end
- stack[top] = round(v)
- else
- top = top - nofregions * n
- local d = top
- local k = top - n
- for i=1,n do
- k = k + 1
- local v = stack[k]
- for r=1,nofregions do
- v = v + stack[d+r] * factors[r]
- end
- stack[k] = round(v)
- d = d + nofregions
+ v = v + stack[d+r] * factors[r]
end
+ stack[k] = round(v)
+ d = d + nofregions
end
end
+ end
- passon = function(operation)
- if operation == 15 then
- setvsindex()
- elseif operation == 16 then
- blend()
- else
- for i=1,top do
- r = r + 1
- result[r] = encode[stack[i]]
- end
- r = r + 1
- result[r] = char(operation) -- maybe use a hash
- top = 0
- end
+ local function p_getstem()
+ local n = 0
+ if top % 2 ~= 0 then
+ n = 1
+ end
+ if top > n then
+ stems = stems + idiv(top-n,2)
end
+ end
+ local function p_getmask()
+ local n = 0
+ if top % 2 ~= 0 then
+ n = 1
+ end
+ if top > n then
+ stems = stems + idiv(top-n,2)
+ end
+ if stems == 0 then
+ return 0
+ elseif stems <= 8 then
+ return 1
+ else
+ return idiv(stems+7,8)
+ end
end
-- end of experiment
@@ -1627,6 +1686,42 @@ do
local justpass = false
+ -- local function decode(str)
+ -- local a, b, c, d, e = byte(str,1,5)
+ -- if a == 28 then
+ -- if c then
+ -- local n = 0x100 * b + c
+ -- if n >= 0x8000 then
+ -- return n - 0x10000
+ -- else
+ -- return n
+ -- end
+ -- end
+ -- elseif a < 32 then
+ -- return false
+ -- elseif a <= 246 then
+ -- return a - 139
+ -- elseif a <= 250 then
+ -- if b then
+ -- return a*256 - 63124 + b
+ -- end
+ -- elseif a <= 254 then
+ -- if b then
+ -- return -a*256 + 64148 - b
+ -- end
+ -- else
+ -- if e then
+ -- local n = 0x100 * b + c
+ -- if n >= 0x8000 then
+ -- return n - 0x10000 + (0x100 * d + e)/0xFFFF
+ -- else
+ -- return n + (0x100 * d + e)/0xFFFF
+ -- end
+ -- end
+ -- end
+ -- return false
+ -- end
+
process = function(tab)
local i = 1
local n = #tab
@@ -1651,9 +1746,9 @@ do
stack[top] = -t*256 + 64148 - tab[i+1]
i = i + 2
else
+ -- a 16.16 float
local n = 0x100 * tab[i+1] + tab[i+2]
- if n >= 0x8000 then
- -- stack[top] = n - 0xFFFF - 1 + (0x100 * tab[i+3] + tab[i+4])/0xFFFF
+ if n >= 0x8000 then
stack[top] = n - 0x10000 + (0x100 * tab[i+3] + tab[i+4])/0xFFFF
else
stack[top] = n + (0x100 * tab[i+3] + tab[i+4])/0xFFFF
@@ -1700,19 +1795,94 @@ do
elseif t == 12 then
i = i + 1
local t = tab[i]
- local a = subactions[t]
- if a then
- a(t)
+ if justpass then
+ if t >= 34 or t <= 37 then -- flexes
+ for i=1,top do
+ r = r + 1 ; result[r] = encode[stack[i]]
+ end
+ r = r + 1 ; result[r] = chars[12]
+ r = r + 1 ; result[r] = chars[t]
+ top = 0
+ else
+ local a = subactions[t]
+ if a then
+ a(t)
+ else
+ top = 0
+ end
+ end
else
- if trace_charstrings then
- showvalue("<subaction>",t)
+ local a = subactions[t]
+ if a then
+ a(t)
+ else
+ if trace_charstrings then
+ showvalue("<subaction>",t)
+ end
+ top = 0
end
- top = 0
end
i = i + 1
elseif justpass then
- passon(t)
- i = i + 1
+ -- todo: local a = passactions
+ if t == 15 then
+ p_setvsindex()
+ i = i + 1
+ elseif t == 16 then
+ local s = p_blend() or 0
+ i = i + s + 1
+ -- cff 1: (when cff2 strip them)
+ elseif t == 1 or t == 3 or t == 18 or operation == 23 then
+ p_getstem() -- at the start
+if true then
+ if top > 0 then
+ for i=1,top do
+ r = r + 1 ; result[r] = encode[stack[i]]
+ end
+ top = 0
+ end
+ r = r + 1 ; result[r] = chars[t]
+else
+ top = 0
+end
+ i = i + 1
+ -- cff 1: (when cff2 strip them)
+ elseif t == 19 or t == 20 then
+ local s = p_getmask() or 0 -- after the stems
+if true then
+ if top > 0 then
+ for i=1,top do
+ r = r + 1 ; result[r] = encode[stack[i]]
+ end
+ top = 0
+ end
+ r = r + 1 ; result[r] = chars[t]
+ for j=1,s do
+ i = i + 1
+ r = r + 1 ; result[r] = chars[tab[i]]
+ end
+else
+ i = i + s
+ top = 0
+end
+ i = i + 1
+ -- cff 1: closepath
+ elseif t == 9 then
+ top = 0
+ i = i + 1
+ elseif t == 13 then
+ local s = hsbw() or 0
+ i = i + s + 1
+ else
+ if top > 0 then
+ for i=1,top do
+ r = r + 1 ; result[r] = encode[stack[i]]
+ end
+ top = 0
+ end
+ r = r + 1 ; result[r] = chars[t]
+ i = i + 1
+ end
else
local a = actions[t]
if a then
@@ -1772,20 +1942,33 @@ do
-- end
local function setbias(globals,locals)
- if version == 1 then
+-- if version == 1 then -- charstring version, not cff
+-- return
+-- 0,
+-- 0
+-- return
+-- 1,
+-- 1
+-- else
+ local g = #globals
+ local l = #locals
return
- false,
- false
- else
- local g, l = #globals, #locals
- return
- ((g < 1240 and 107) or (g < 33900 and 1131) or 32768) + 1,
- ((l < 1240 and 107) or (l < 33900 and 1131) or 32768) + 1
- end
+ ((g < 1240 and 107) or (g < 33900 and 1131) or 32768) + 1,
+ ((l < 1240 and 107) or (l < 33900 and 1131) or 32768) + 1
+-- end
end
local function processshape(tab,index)
+ if not tab then
+ glyphs[index] = {
+ boundingbox = { 0, 0, 0, 0 },
+ width = 0,
+ name = charset and charset[index] or nil,
+ }
+ return
+ end
+
tab = bytetable(tab)
x = 0
@@ -1801,7 +1984,6 @@ do
ymin = 0
ymax = 0
checked = false
-
if trace_charstrings then
report("glyph: %i",index)
report("data : % t",tab)
@@ -1921,19 +2103,20 @@ do
globalbias, localbias = setbias(globals,locals)
nominalwidth, defaultwidth = setwidths(dictionary.private)
- startparsing(fontdata,data,streams)
-
- for index=1,#charstrings do
- processshape(charstrings[index],index-1)
- charstrings[index] = nil -- free memory (what if used more often?)
+ if charstrings then
+ startparsing(fontdata,data,streams)
+ for index=1,#charstrings do
+ processshape(charstrings[index],index-1)
+-- charstrings[index] = nil -- free memory (what if used more often?)
+ end
+ stopparsing(fontdata,data)
+ else
+ report("no charstrings")
end
-
- stopparsing(fontdata,data)
-
return glyphs
end
- parsecharstring = function(fontdata,data,dictionary,tab,glphs,index,doshapes,tversion)
+ parsecharstring = function(fontdata,data,dictionary,tab,glphs,index,doshapes,tversion,streams)
keepcurve = doshapes
version = tversion
@@ -1944,6 +2127,8 @@ do
vsindex = dictionary.vsindex or 0
glyphs = glphs or { }
+ justpass = streams == true
+
globalbias, localbias = setbias(globals,locals)
nominalwidth, defaultwidth = setwidths(dictionary.private)
@@ -2118,7 +2303,7 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams)
local format = readbyte(f)
if format == 1 then
for i=0,nofglyphs do -- notdef included (needs checking)
- local index = readbyte(i)
+ local index = readbyte(f)
fdindex[i] = index
if index > maxindex then
maxindex = index
@@ -2149,23 +2334,27 @@ local function readfdselect(f,fontdata,data,glyphs,doshapes,version,streams)
-- hm, always
if maxindex >= 0 then
local cidarray = cid.fdarray
- setposition(f,header.offset+cidarray)
- local dictionaries = readlengths(f)
- for i=1,#dictionaries do
- dictionaries[i] = readstring(f,dictionaries[i])
- end
- parsedictionaries(data,dictionaries)
- cid.dictionaries = dictionaries
- readcidprivates(f,data)
- for i=1,#dictionaries do
- readlocals(f,data,dictionaries[i])
- end
- startparsing(fontdata,data,streams)
- for i=1,#charstrings do
- parsecharstring(fontdata,data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version)
- charstrings[i] = nil
+ if cidarray then
+ setposition(f,header.offset+cidarray)
+ local dictionaries = readlengths(f)
+ for i=1,#dictionaries do
+ dictionaries[i] = readstring(f,dictionaries[i])
+ end
+ parsedictionaries(data,dictionaries)
+ cid.dictionaries = dictionaries
+ readcidprivates(f,data)
+ for i=1,#dictionaries do
+ readlocals(f,data,dictionaries[i])
+ end
+ startparsing(fontdata,data,streams)
+ for i=1,#charstrings do
+ parsecharstring(fontdata,data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version,streams)
+-- charstrings[i] = nil
+ end
+ stopparsing(fontdata,data)
+ else
+ report("no cid array")
end
- stopparsing(fontdata,data)
end
end
@@ -2184,7 +2373,7 @@ local function cleanup(data,dictionaries)
end
function readers.cff(f,fontdata,specification)
- local tableoffset = gotodatatable(f,fontdata,"cff",specification.details)
+ local tableoffset = gotodatatable(f,fontdata,"cff",specification.details or specification.glyphs)
if tableoffset then
local header = readheader(f)
if header.major ~= 1 then
@@ -2207,14 +2396,17 @@ function readers.cff(f,fontdata,specification)
--
local dic = dictionaries[1]
local cid = dic.cid
- fontdata.cffinfo = {
- familynamename = dic.familyname,
+ --
+ local cffinfo = {
+ familyname = dic.familyname,
fullname = dic.fullname,
boundingbox = dic.boundingbox,
weight = dic.weight,
italicangle = dic.italicangle,
underlineposition = dic.underlineposition,
underlinethickness = dic.underlinethickness,
+ defaultwidth = dic.defaultwidthx,
+ nominalwidth = dic.nominalwidthx,
monospaced = dic.monospaced,
}
fontdata.cidinfo = cid and {
@@ -2222,13 +2414,31 @@ function readers.cff(f,fontdata,specification)
ordering = cid.ordering,
supplement = cid.supplement,
}
+ fontdata.cffinfo = cffinfo
--
- if specification.glyphs then
- local all = specification.shapes or false
+ local all = specification.shapes or specification.streams or false
+ if specification.glyphs or all then
if cid and cid.fdselect then
- readfdselect(f,fontdata,data,glyphs,all,"cff")
+ readfdselect(f,fontdata,data,glyphs,all,"cff",specification.streams)
else
- readnoselect(f,fontdata,data,glyphs,all,"cff")
+ readnoselect(f,fontdata,data,glyphs,all,"cff",specification.streams)
+ end
+ end
+ local private = dic.private
+ if private then
+ local data = private.data
+ if type(data) == "table" then
+ cffinfo.defaultwidth = data.defaultwidth or cffinfo.defaultwidth
+ cffinfo.nominalwidth = data.nominalwidth or cffinfo.nominalwidth
+ cffinfo.bluevalues = data.bluevalues
+ cffinfo.otherblues = data.otherblues
+ cffinfo.familyblues = data.familyblues
+ cffinfo.familyotherblues = data.familyotherblues
+ cffinfo.bluescale = data.bluescale
+ cffinfo.blueshift = data.blueshift
+ cffinfo.bluefuzz = data.bluefuzz
+ cffinfo.stdhw = data.stdhw
+ cffinfo.stdvw = data.stdvw
end
end
cleanup(data,dictionaries)
@@ -2267,7 +2477,7 @@ function readers.cff2(f,fontdata,specification)
data.factors = specification.factors
--
local cid = data.dictionaries[1].cid
- local all = specification.shapes or false
+ local all = specification.shapes or specification.streams or false
if cid and cid.fdselect then
readfdselect(f,fontdata,data,glyphs,all,"cff2",specification.streams)
else
@@ -2300,7 +2510,7 @@ function readers.cffcheck(filename)
dictionaries = dictionaries,
strings = strings,
glyphs = glyphs,
- nofglyphs = 4,
+ nofglyphs = 0,
}
--
parsedictionaries(data,dictionaries,"cff")
diff --git a/tex/context/base/mkiv/font-cft.lua b/tex/context/base/mkiv/font-cft.lua
index 83227ca4a..2e1610f17 100644
--- a/tex/context/base/mkiv/font-cft.lua
+++ b/tex/context/base/mkiv/font-cft.lua
@@ -248,6 +248,16 @@ do
mathitalics = t_boolean,
textitalics = t_boolean,
finalized = t_boolean,
+ effect = {
+ effect = t_cardinal,
+ width = t_float,
+ factor = t_float,
+ hfactor = t_float,
+ vfactor = t_float,
+ wdelta = t_float,
+ hdelta = t_float,
+ ddelta = t_float,
+ }
},
parameters = {
mathsize = t_cardinal,
diff --git a/tex/context/base/mkiv/font-chk.lua b/tex/context/base/mkiv/font-chk.lua
index 3613432c1..ab145ce4d 100644
--- a/tex/context/base/mkiv/font-chk.lua
+++ b/tex/context/base/mkiv/font-chk.lua
@@ -66,14 +66,12 @@ local hpack_node = node.hpack
local nuts = nodes.nuts
local tonut = nuts.tonut
-local tonode = nuts.tonode
-
-local getfont = nuts.getfont
-local getchar = nuts.getchar
+local isglyph = nuts.isglyph
local setchar = nuts.setchar
-local traverse_id = nuts.traverse_id
+local nextglyph = nuts.traversers.glyph
+
local remove_node = nuts.remove
local insert_node_after = nuts.insert_after
@@ -142,7 +140,7 @@ local mapping = allocate { -- this is just an experiment to illustrate some prin
table.setmetatableindex(mapping,
function(t,k)
- v = "placeholder unknown gray"
+ local v = "placeholder unknown gray"
t[k] = v
return v
end
@@ -196,7 +194,10 @@ local variants = allocate {
{ tag = "yellow", r = .6, g = .6, b = 0 },
}
-local pdf_blob = "pdf: q %.6F 0 0 %.6F 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q"
+-- bah .. low level pdf ... should be a rule or plugged in
+
+----- pdf_blob = "pdf: q %.6F 0 0 %.6F 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q"
+local pdf_blob = "q %.6F 0 0 %.6F 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q"
local cache = { } -- saves some tables but not that impressive
@@ -235,8 +236,8 @@ local function addmissingsymbols(tfmdata) -- we can have an alternative with rul
width = size*fake.width,
height = size*fake.height,
depth = size*fake.depth,
- -- bah .. low level pdf ... should be a rule or plugged in
- commands = { { "special", formatters[pdf_blob](scale,scale,r,g,b,r,g,b,fake.code) } }
+ -- commands = { { "special", formatters[pdf_blob](scale,scale,r,g,b,r,g,b,fake.code) } }
+ commands = { { "pdf", formatters[pdf_blob](scale,scale,r,g,b,r,g,b,fake.code) } }
}
cache[hash] = char
end
@@ -278,7 +279,7 @@ end
local function placeholder(font,char)
local tfmdata = fontdata[font]
- local category = chardata[char].category
+ local category = chardata[char].category or "unknown"
local fakechar = mapping[category]
local slot = getprivateslot(font,fakechar)
if not slot then
@@ -292,15 +293,12 @@ checkers.placeholder = placeholder
function checkers.missing(head)
local lastfont, characters, found = nil, nil, nil
- head = tonut(head)
- for n in traverse_id(glyph_code,head) do -- faster than while loop so we delay removal
- local font = getfont(n)
- local char = getchar(n)
+ for n, char, font in nextglyph, head do -- faster than while loop so we delay removal
if font ~= lastfont then
characters = fontcharacters[font]
lastfont = font
end
- if font > 0 and not characters[char] and is_character[chardata[char].category] then
+ if font > 0 and not characters[char] and is_character[chardata[char].category or "unknown"] then
if action == "remove" then
onetimemessage(font,char,"missing (will be deleted)")
elseif action == "replace" then
@@ -324,7 +322,8 @@ function checkers.missing(head)
elseif action == "replace" then
for i=1,#found do
local node = found[i]
- local kind, char = placeholder(getfont(node),getchar(node))
+ local char, font = isglyph(node)
+ local kind, char = placeholder(font,char)
if kind == "node" then
insert_node_after(head,node,tonut(char))
head = remove_node(head,node,true)
@@ -337,7 +336,7 @@ function checkers.missing(head)
else
-- maye write a report to the log
end
- return tonode(head), false
+ return head
end
local relevant = {
@@ -362,6 +361,9 @@ local function getmissing(id)
local messages = shared and shared.messages
if messages then
local filename = d.properties.filename
+ if not filename then
+ filename = tostring(d)
+ end
local tf = t[filename] or { }
for i=1,#relevant do
local tm = messages[relevant[i]]
@@ -390,7 +392,6 @@ checkers.getmissing = getmissing
do
local reported = true
- local tracked = false
callback.register("glyph_not_found",function(font,char)
if font > 0 then
@@ -408,7 +409,6 @@ do
trackers.register("fonts.missing", function(v)
if v then
enableaction("processors","fonts.checkers.missing")
- tracked = true
else
disableaction("processors","fonts.checkers.missing")
end
@@ -419,27 +419,25 @@ do
end)
logs.registerfinalactions(function()
--- if tracked then
- local collected, details = getmissing()
- if next(collected) then
+ local collected, details = getmissing()
+ if next(collected) then
+ for filename, list in sortedhash(details) do
+ logs.startfilelogging(report,"missing characters",filename)
+ for u, v in sortedhash(list) do
+ report("%4i %U %c %s",v,u,u,chardata[u].description)
+ end
+ logs.stopfilelogging()
+ end
+ if logs.loggingerrors() then
for filename, list in sortedhash(details) do
- logs.startfilelogging(report,"missing characters",filename)
+ logs.starterrorlogging(report,"missing characters",filename)
for u, v in sortedhash(list) do
report("%4i %U %c %s",v,u,u,chardata[u].description)
end
- logs.stopfilelogging()
- end
- if logs.loggingerrors() then
- for filename, list in sortedhash(details) do
- logs.starterrorlogging(report,"missing characters",filename)
- for u, v in sortedhash(list) do
- report("%4i %U %c %s",v,u,u,chardata[u].description)
- end
- logs.stoperrorlogging()
- end
+ logs.stoperrorlogging()
end
end
--- end
+ end
end)
end
@@ -507,3 +505,31 @@ local dummies_specification = {
registerotffeature(dummies_specification)
registerafmfeature(dummies_specification)
+
+--
+
+local function addvisualspace(tfmdata)
+ local spacechar = tfmdata.characters[32]
+ if spacechar and not spacechar.commands then
+ local w = spacechar.width
+ local h = tfmdata.parameters.xheight
+ local c = {
+ width = w,
+ commands = { { "rule", h, w } }
+ }
+ local u = addprivate(tfmdata, "visualspace", c)
+ end
+end
+
+local visualspace_specification = {
+ name = "visualspace",
+ description = "visual space",
+ default = true,
+ manipulators = {
+ base = addvisualspace,
+ node = addvisualspace,
+ }
+}
+
+registerotffeature(visualspace_specification)
+registerafmfeature(visualspace_specification)
diff --git a/tex/context/base/mkiv/font-col.lua b/tex/context/base/mkiv/font-col.lua
index 7bbaf31cb..d197c7c85 100644
--- a/tex/context/base/mkiv/font-col.lua
+++ b/tex/context/base/mkiv/font-col.lua
@@ -19,15 +19,11 @@ local fastcopy = table.fastcopy
local formatters = string.formatters
local nuts = nodes.nuts
-local tonut = nuts.tonut
-
-local getfont = nuts.getfont
-local getchar = nuts.getchar
local setfont = nuts.setfont
-local traverse_id = nuts.traverse_id
-local traverse_char = nuts.traverse_char
+----- traverse_char = nuts.traverse_char
+local nextchar = nuts.traversers.char
local settings_to_hash = utilities.parsers.settings_to_hash
@@ -47,28 +43,38 @@ collections.definitions = definitions
local vectors = collections.vectors or { }
collections.vectors = vectors
-local fonthashes = fonts.hashes
-local fonthelpers = fonts.helpers
-
-local fontdata = fonthashes.identifiers
-local fontquads = fonthashes.quads
-local chardata = fonthashes.characters
-local propdata = fonthashes.properties
+local helpers = fonts.helpers
+local charcommand = helpers.commands.char
+local rightcommand = helpers.commands.right
+local addprivate = helpers.addprivate
+local hasprivate = helpers.hasprivate
+local fontpatternhassize = helpers.fontpatternhassize
-local addprivate = fonthelpers.addprivate
-local hasprivate = fonthelpers.hasprivate
+local hashes = fonts.hashes
+local fontdata = hashes.identifiers
+local fontquads = hashes.quads
+local chardata = hashes.characters
+local propdata = hashes.properties
+local mathparameters = hashes.mathparameters
local currentfont = font.current
local addcharacters = font.addcharacters
-local fontpatternhassize = fonts.helpers.fontpatternhassize
-
local implement = interfaces.implement
local list = { }
local current = 0
local enabled = false
+local validvectors = table.setmetatableindex(function(t,k)
+ local v = false
+ if not mathparameters[k] then
+ v = vectors[k]
+ end
+ t[k] = v
+ return v
+end)
+
local function checkenabled()
-- a bit ugly but nicer than a fuzzy state while defining math
if next(vectors) then
@@ -113,6 +119,23 @@ function collections.define(name,font,ranges,details)
end
details = settings_to_hash(details)
-- todo, combine per font start/stop as arrays
+ local offset = details.offset
+ if type(offset) == "string" then
+ offset = characters.getrange(offset,true) or false
+ else
+ offset = tonumber(offset) or false
+ end
+ local target = details.target
+ if type(target) == "string" then
+ target = characters.getrange(target,true) or false
+ else
+ target = tonumber(target) or false
+ end
+ local rscale = tonumber (details.rscale) or 1
+ local force = toboolean(details.force,true)
+ local check = toboolean(details.check,true)
+ local factor = tonumber(details.factor)
+ local features = details.features
for s in gmatch(ranges,"[^, ]+") do
local start, stop, description, gaps = characters.getrange(s,true)
if start and stop then
@@ -127,24 +150,19 @@ function collections.define(name,font,ranges,details)
end
end
end
- local offset = details.offset
- if type(offset) == "string" then
- local start = characters.getrange(offset,true)
- offset = start or false
- else
- offset = tonumber(offset) or false
- end
d[#d+1] = {
font = font,
start = start,
stop = stop,
gaps = gaps,
offset = offset,
- rscale = tonumber (details.rscale) or 1,
- force = toboolean(details.force,true),
- check = toboolean(details.check,true),
- factor = tonumber(details.factor),
- features = details.features,
+ target = target,
+ rscale = rscale,
+ force = force,
+ check = check,
+ method = details.method,
+ factor = factor,
+ features = features,
}
end
end
@@ -163,6 +181,32 @@ end
-- check: when true, only set when present in font
-- force: when false, then not set when already set
+local uccodes = characters.uccodes
+local lccodes = characters.lccodes
+
+local methods = {
+ lowercase = function(oldchars,newchars,vector,start,stop,cloneid)
+ for k, v in next, oldchars do
+ if k >= start and k <= stop then
+ local lccode = lccodes[k]
+ if k ~= lccode and newchars[lccode] then
+ vector[k] = { cloneid, lccode }
+ end
+ end
+ end
+ end,
+ uppercase = function(oldchars,newchars,vector,start,stop,cloneid)
+ for k, v in next, oldchars do
+ if k >= start and k <= stop then
+ local uccode = uccodes[k]
+ if k ~= uccode and newchars[uccode] then
+ vector[k] = { cloneid, uccode }
+ end
+ end
+ end
+ end,
+}
+
function collections.clonevector(name)
statistics.starttiming(fonts)
if trace_collecting then
@@ -179,7 +223,9 @@ function collections.clonevector(name)
local check = definition.check
local force = definition.force
local offset = definition.offset or start
- local remap = definition.remap
+ local remap = definition.remap -- not used
+ local target = definition.target
+ local method = definition.method
local cloneid = list[i]
local oldchars = fontdata[current].characters
local newchars = fontdata[cloneid].characters
@@ -188,28 +234,60 @@ function collections.clonevector(name)
vector.factor = factor
end
if trace_collecting then
- report_fonts("remapping font %a to %a for range %U - %U",current,cloneid,start,stop)
+ if target then
+ report_fonts("remapping font %a to %a for range %U - %U, offset %X, target %U",current,cloneid,start,stop,offset,target)
+ else
+ report_fonts("remapping font %a to %a for range %U - %U, offset %X",current,cloneid,start,stop,offset)
+ end
end
- if check then
- for unicode = start, stop do
- local unic = unicode + offset - start
- if not newchars[unicode] then
- -- not in font
- elseif force or (not vector[unic] and not oldchars[unic]) then
- if remap then
- vector[unic] = { cloneid, remap[unicode] }
- else
+ if method then
+ method = methods[method]
+ end
+ if method then
+ method(oldchars,newchars,vector,start,stop,cloneid)
+ elseif check then
+ if target then
+ for unicode = start, stop do
+ local unic = unicode + offset - start
+ if not newchars[target] then
+ -- not in font
+ elseif force or (not vector[unic] and not oldchars[unic]) then
+ vector[unic] = { cloneid, target }
+ end
+ target = target + 1
+ end
+ elseif remap then
+ -- not used
+ else
+ for unicode = start, stop do
+ local unic = unicode + offset - start
+ if not newchars[unicode] then
+ -- not in font
+ elseif force or (not vector[unic] and not oldchars[unic]) then
vector[unic] = cloneid
end
end
end
else
- for unicode = start, stop do
- local unic = unicode + offset - start
- if force or (not vector[unic] and not oldchars[unic]) then
- if remap then
+ if target then
+ for unicode = start, stop do
+ local unic = unicode + offset - start
+ if force or (not vector[unic] and not oldchars[unic]) then
+ vector[unic] = { cloneid, target }
+ end
+ target = target + 1
+ end
+ elseif remap then
+ for unicode = start, stop do
+ local unic = unicode + offset - start
+ if force or (not vector[unic] and not oldchars[unic]) then
vector[unic] = { cloneid, remap[unicode] }
- else
+ end
+ end
+ else
+ for unicode = start, stop do
+ local unic = unicode + offset - start
+ if force or (not vector[unic] and not oldchars[unic]) then
vector[unic] = cloneid
end
end
@@ -219,8 +297,11 @@ function collections.clonevector(name)
if trace_collecting then
report_fonts("activating collection %a for font %a",name,current)
end
- checkenabled()
statistics.stoptiming(fonts)
+ -- for WS: needs checking
+ if validvectors[current] then
+ checkenabled()
+ end
end
-- we already have this parser
@@ -284,13 +365,16 @@ local function monoslot(font,char,parent,factor)
local width = factor * fontquads[parent]
local character = characters[char]
if character then
+ -- runtime patching of the font (can only be new characters)
+ -- instead of messing with existing dimensions
local data = {
+ -- no features so a simple copy
width = width,
height = character.height,
depth = character.depth,
commands = {
- { "right", (width - character.width or 0)/2 },
- { "slot", 0, char }
+ rightcommand[(width - character.width or 0)/2],
+ charcommand[char],
}
}
local u = addprivate(tfmdata, privatename, data)
@@ -308,12 +392,9 @@ local function monoslot(font,char,parent,factor)
end
function collections.process(head) -- this way we keep feature processing
- local done = false
- for n in traverse_char(tonut(head)) do
- local font = getfont(n)
- local vector = vectors[font]
+ for n, char, font in nextchar, head do
+ local vector = validvectors[font]
if vector then
- local char = getchar(n)
local vect = vector[char]
if not vect then
-- keep it
@@ -326,7 +407,6 @@ function collections.process(head) -- this way we keep feature processing
)
end
setfont(n,newfont,newchar)
- done = true
else
local fakemono = vector.factor
if trace_collecting then
@@ -339,11 +419,10 @@ function collections.process(head) -- this way we keep feature processing
else
setfont(n,vect)
end
- done = true
end
end
end
- return head, done
+ return head
end
function collections.found(font,char) -- this way we keep feature processing
diff --git a/tex/context/base/mkiv/font-col.mkvi b/tex/context/base/mkiv/font-col.mkvi
index a9c461e44..7ba92b526 100644
--- a/tex/context/base/mkiv/font-col.mkvi
+++ b/tex/context/base/mkiv/font-col.mkvi
@@ -23,6 +23,11 @@
% \definefontfallback [whatever] [Slanted] [0x0060-0x007F] [force=yes]
% \definefontfallback [whatever] [Bold] [0x0080-0x00FF,0x00A0-0x00AF] [rscale=1.2]
% \definefontfallback [whatever] [BoldSlanted] [0x00C0-0x00C7] [check=yes,force=yes]
+%
+% \definefontfeature [emboldened] [effect={width=0.1,delta=0.4,factor=0.3}]
+% \definefontsynonym [SansEmboldened] [Sans] [features=emboldened]
+% \definefontfallback[FakeSansCaps] [SansEmboldened] [0x0000-0xFFFF] [rscale=.8,method=uppercase]
+% \definefontsynonym [SansCaps] [file:MyriadPro-Regular.otf] [fallbacks=FakeSansCaps]
\writestatus{loading}{ConTeXt Font Macros / Collections}
diff --git a/tex/context/base/mkiv/font-con.lua b/tex/context/base/mkiv/font-con.lua
index add646da1..354fd4ac3 100644
--- a/tex/context/base/mkiv/font-con.lua
+++ b/tex/context/base/mkiv/font-con.lua
@@ -46,10 +46,11 @@ constructors.namemode = "fullpath" -- will be a function
constructors.version = 1.01
constructors.cache = containers.define("fonts", "constructors", constructors.version, false)
-constructors.privateoffset = 0xF0000 -- 0x10FFFF | context also uses privates: 0xE000-0xEFFF
-
+constructors.privateoffset = fonts.privateoffsets.textbase or 0xF0000
constructors.cacheintex = true -- so we see the original table in fonts.font
+constructors.addtounicode = true
+
-- This might become an interface:
local designsizes = allocate()
@@ -98,6 +99,24 @@ function constructors.getprivate(tfmdata)
return private
end
+function constructors.setmathparameter(tfmdata,name,value)
+ local m = tfmdata.mathparameters
+ local c = tfmdata.MathConstants
+ if m then
+ m[name] = value
+ end
+ if c and c ~= m then
+ c[name] = value
+ end
+end
+
+function constructors.getmathparameter(tfmdata,name)
+ local p = tfmdata.mathparameters or tfmdata.MathConstants
+ if p then
+ return p[name]
+ end
+end
+
--[[ldx--
<p>Beware, the boundingbox is passed as reference so we may not overwrite it
in the process; numbers are of course copies. Here 65536 equals 1pt. (Due to
@@ -407,7 +426,10 @@ function constructors.scale(tfmdata,specification)
targetparameters.forcedsize = forcedsize -- context specific
targetparameters.extrafactor = extrafactor -- context specific
--
+ local addtounicode = constructors.addtounicode
+ --
local tounicode = fonts.mappings.tounicode
+ local unknowncode = tounicode(0xFFFD)
--
local defaultwidth = resources.defaultwidth or 0
local defaultheight = resources.defaultheight or 0
@@ -455,7 +477,8 @@ function constructors.scale(tfmdata,specification)
local psname = properties.psname or tfmdata.psname
local name = properties.name or tfmdata.name
--
- -- the psname used in pdf file as well as for selecting subfont in ttc
+ -- The psname used in pdf file as well as for selecting subfont in ttc although
+ -- we don't need that subfont look up here (mapfile stuff).
--
local psname, psfixed = fixedpsname(psname,fontname or fullname or file.nameonly(filename))
--
@@ -477,20 +500,28 @@ function constructors.scale(tfmdata,specification)
target.shrink = expansion.shrink
target.step = expansion.step
end
+ -- slanting
+ local slantfactor = parameters.slantfactor or 0
+ if slantfactor ~= 0 then
+ target.slant = slantfactor * 1000
+ else
+ target.slant = 0
+ end
-- widening
local extendfactor = parameters.extendfactor or 0
if extendfactor ~= 0 and extendfactor ~= 1 then
hdelta = hdelta * extendfactor
- target.extend = extendfactor * 1000 -- extent ?
+ target.extend = extendfactor * 1000
else
target.extend = 1000 -- extent ?
end
- -- slanting
- local slantfactor = parameters.slantfactor or 0
- if slantfactor ~= 0 then
- target.slant = slantfactor * 1000
+ -- squeezing
+ local squeezefactor = parameters.squeezefactor or 0
+ if squeezefactor ~= 0 and squeezefactor ~= 1 then
+ vdelta = vdelta * squeezefactor
+ target.squeeze = squeezefactor * 1000
else
- target.slant = 0
+ target.squeeze = 1000 -- extent ?
end
-- effects
local mode = parameters.mode or 0
@@ -499,7 +530,7 @@ function constructors.scale(tfmdata,specification)
end
local width = parameters.width or 0
if width ~= 0 then
- target.width = width
+ target.width = width * delta * 1000 / 655360
end
--
targetparameters.factor = delta
@@ -565,6 +596,7 @@ function constructors.scale(tfmdata,specification)
targetparameters.descender = delta * descender
end
--
+-- inspect(targetparameters)
constructors.enhanceparameters(targetparameters) -- official copies for us, now virtual
--
local protrusionfactor = (targetquad ~= 0 and 1000/targetquad) or 0
@@ -708,11 +740,19 @@ function constructors.scale(tfmdata,specification)
end
end
local isunicode = description.unicode
- if isunicode then
- chr.unicode = isunicode
- chr.tounicode = tounicode(isunicode)
- -- in luatex > 0.85 we can do this:
- -- chr.tounicode = isunicode
+ if addtounicode then
+ if isunicode then
+ chr.unicode = isunicode
+ chr.tounicode = tounicode(isunicode)
+ -- in luatex > 0.85 we can do this:
+ -- chr.tounicode = isunicode
+ else
+ chr.tounicode = unknowncode
+ end
+ else
+ if isunicode then
+ chr.unicode = isunicode
+ end
end
if hasquality then
-- we could move these calculations elsewhere (saves calculations)
@@ -742,12 +782,15 @@ function constructors.scale(tfmdata,specification)
local t = { }
for i=1,#vv do
local vvi = vv[i]
- t[i] = {
- ["start"] = (vvi["start"] or 0)*vdelta,
- ["end"] = (vvi["end"] or 0)*vdelta,
- ["advance"] = (vvi["advance"] or 0)*vdelta,
- ["extender"] = vvi["extender"],
- ["glyph"] = vvi["glyph"],
+ local s = vvi["start"] or 0
+ local e = vvi["end"] or 0
+ local a = vvi["advance"] or 0
+ t[i] = { -- zero check nicer for 5.3
+ ["start"] = s == 0 and 0 or s * vdelta,
+ ["end"] = e == 0 and 0 or e * vdelta,
+ ["advance"] = a == 0 and 0 or a * vdelta,
+ ["extender"] = vvi["extender"],
+ ["glyph"] = vvi["glyph"],
}
end
chr.vert_variants = t
@@ -757,12 +800,15 @@ function constructors.scale(tfmdata,specification)
local t = { }
for i=1,#hv do
local hvi = hv[i]
- t[i] = {
- ["start"] = (hvi["start"] or 0)*hdelta,
- ["end"] = (hvi["end"] or 0)*hdelta,
- ["advance"] = (hvi["advance"] or 0)*hdelta,
- ["extender"] = hvi["extender"],
- ["glyph"] = hvi["glyph"],
+ local s = hvi["start"] or 0
+ local e = hvi["end"] or 0
+ local a = hvi["advance"] or 0
+ t[i] = { -- zero check nicer for 5.3
+ ["start"] = s == 0 and 0 or s * hdelta,
+ ["end"] = e == 0 and 0 or e * hdelta,
+ ["advance"] = a == 0 and 0 or a * hdelta,
+ ["extender"] = hvi["extender"],
+ ["glyph"] = hvi["glyph"],
}
end
chr.horiz_variants = t
@@ -781,7 +827,10 @@ function constructors.scale(tfmdata,specification)
if stackmath then
local mk = character.mathkerns
if mk then
- local tr, tl, br, bl = mk.topright, mk.topleft, mk.bottomright, mk.bottomleft
+ local tr = mk.topright
+ local tl = mk.topleft
+ local br = mk.bottomright
+ local bl = mk.bottomleft
chr.mathkern = { -- singular -> should be patched in luatex !
top_right = tr and mathkerns(tr,vdelta) or nil,
top_left = tl and mathkerns(tl,vdelta) or nil,
@@ -876,7 +925,7 @@ function constructors.scale(tfmdata,specification)
else
chr.commands = vc
end
- chr.index = nil
+ -- chr.index = nil
end
end
targetcharacters[unicode] = chr
@@ -886,15 +935,14 @@ function constructors.scale(tfmdata,specification)
--
constructors.aftercopyingcharacters(target,tfmdata)
--
- constructors.trytosharefont(target,tfmdata)
+ constructors.trytosharefont(target,tfmdata)
--
-- catch inconsistencies
--
local vfonts = target.fonts
--- if isvirtual then
-if isvirtual or target.type == "virtual" or properties.virtualized then
+ if isvirtual or target.type == "virtual" or properties.virtualized then
properties.virtualized = true
-target.type = "virtual"
+ target.type = "virtual"
if not vfonts or #vfonts == 0 then
target.fonts = { { id = 0 } }
end
@@ -947,12 +995,16 @@ function constructors.finalize(tfmdata)
parameters.width = 0
end
--
+ if not parameters.slantfactor then
+ parameters.slantfactor = tfmdata.slant or 0
+ end
+ --
if not parameters.extendfactor then
parameters.extendfactor = tfmdata.extend or 0
end
--
- if not parameters.slantfactor then
- parameters.slantfactor = tfmdata.slant or 0
+ if not parameters.squeezefactor then
+ parameters.squeezefactor = tfmdata.squeeze or 0
end
--
local designsize = parameters.designsize
@@ -988,24 +1040,22 @@ function constructors.finalize(tfmdata)
properties.virtualized = tfmdata.type == "virtual"
end
--
- if not tfmdata.properties then
- tfmdata.properties = {
- fontname = tfmdata.fontname,
- filename = tfmdata.filename,
- fullname = tfmdata.fullname,
- name = tfmdata.name,
- psname = tfmdata.psname,
- --
- encodingbytes = tfmdata.encodingbytes or 1,
- embedding = tfmdata.embedding or "subset",
- tounicode = tfmdata.tounicode or 1,
- cidinfo = tfmdata.cidinfo or nil,
- format = tfmdata.format or "type1",
- direction = tfmdata.direction or 0,
- writingmode = tfmdata.writingmode or "horizontal",
- identity = tfmdata.identity or "horizontal",
- }
- end
+ properties.fontname = tfmdata.fontname
+ properties.filename = tfmdata.filename
+ properties.fullname = tfmdata.fullname
+ properties.name = tfmdata.name
+ properties.psname = tfmdata.psname
+ --
+ properties.encodingbytes = tfmdata.encodingbytes or 1
+ properties.embedding = tfmdata.embedding or "subset"
+ properties.tounicode = tfmdata.tounicode or 1
+ properties.cidinfo = tfmdata.cidinfo or nil
+ properties.format = tfmdata.format or "type1"
+ properties.direction = tfmdata.direction or 0
+ properties.writingmode = tfmdata.writingmode or "horizontal"
+ properties.identity = tfmdata.identity or "horizontal"
+ properties.usedbitmap = tfmdata.usedbitmap
+ --
if not tfmdata.resources then
tfmdata.resources = { }
end
@@ -1043,8 +1093,9 @@ function constructors.finalize(tfmdata)
tfmdata.stretch = nil
tfmdata.shrink = nil
tfmdata.step = nil
- tfmdata.extend = nil
tfmdata.slant = nil
+ tfmdata.extend = nil
+ tfmdata.squeeze = nil
tfmdata.mode = nil
tfmdata.width = nil
tfmdata.units = nil
@@ -1097,7 +1148,18 @@ hashmethods.normal = function(list)
-- no need to add to hash (maybe we need a skip list)
else
n = n + 1
- s[n] = k .. '=' .. tostring(v)
+ if type(v) == "table" then
+ -- table.sequenced
+ local t = { }
+ local m = 0
+ for k, v in next, v do
+ m = m + 1
+ t[m] = k .. '=' .. tostring(v)
+ end
+ s[n] = k .. '={' .. concat(t,",") .. "}"
+ else
+ s[n] = k .. '=' .. tostring(v)
+ end
end
end
if n > 0 then
@@ -1115,7 +1177,9 @@ loose our testcases for <l n='luatex'/>.</p>
--ldx]]--
function constructors.hashinstance(specification,force)
- local hash, size, fallbacks = specification.hash, specification.size, specification.fallbacks
+ local hash = specification.hash
+ local size = specification.size
+ local fallbacks = specification.fallbacks
if force or not hash then
hash = constructors.hashfeatures(specification)
specification.hash = hash
@@ -1553,7 +1617,8 @@ end
-- while typesetting
function constructors.collectprocessors(what,tfmdata,features,trace,report)
- local processes, nofprocesses = { }, 0
+ local processes = { }
+ local nofprocesses = 0
if features and next(features) then
local properties = tfmdata.properties
local whathandler = handlers[what]
diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua
index 87885f64f..6847a2b8d 100644
--- a/tex/context/base/mkiv/font-ctx.lua
+++ b/tex/context/base/mkiv/font-ctx.lua
@@ -12,21 +12,23 @@ if not modules then modules = { } end modules ['font-ctx'] = {
-- 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 tostring, next, type, rawget, tonumber = tostring, next, type, rawget, tonumber
local format, gmatch, match, find, lower, upper, gsub, byte, topattern = string.format, string.gmatch, string.match, string.find, string.lower, string.upper, string.gsub, string.byte, string.topattern
local concat, serialize, sort, fastcopy, mergedtable = table.concat, table.serialize, table.sort, table.fastcopy, table.merged
local sortedhash, sortedkeys, sequenced = table.sortedhash, table.sortedkeys, table.sequenced
-local settings_to_hash, hash_to_string, settings_to_array = utilities.parsers.settings_to_hash, utilities.parsers.hash_to_string, utilities.parsers.settings_to_array
+local parsers = utilities.parsers
+local settings_to_hash, hash_to_string, settings_to_array = parsers.settings_to_hash, parsers.hash_to_string, parsers.settings_to_array
local formatcolumns = utilities.formatters.formatcolumns
local mergehashes = utilities.parsers.mergehashes
local formatters = string.formatters
local basename = file.basename
-local tostring, next, type, rawget, tonumber = tostring, next, type, rawget, tonumber
local utfchar, utfbyte = utf.char, utf.byte
local round = math.round
+local context, commands = context, commands
+
local P, S, C, Cc, Cf, Cg, Ct, lpegmatch = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cf, lpeg.Cg, lpeg.Ct, lpeg.match
local trace_features = false trackers.register("fonts.features", function(v) trace_features = v end)
@@ -66,6 +68,8 @@ local hashes = fonts.hashes
local currentfont = font.current
local definefont = font.define
+local getprivateslot = helpers.getprivateslot
+
local cleanname = names.cleanname
local encodings = fonts.encodings
@@ -75,11 +79,12 @@ local aglunicodes = nil -- delayed loading
local nuts = nodes.nuts
local tonut = nuts.tonut
+local nextchar = nuts.traversers.char
+
local getattr = nuts.getattr
local setattr = nuts.setattr
local getprop = nuts.getprop
local setprop = nuts.setprop
-local getfont = nuts.getfont
local setsubtype = nuts.setsubtype
local texgetattribute = tex.getattribute
@@ -158,17 +163,8 @@ helpers.name = getfontname
local addformatter = utilities.strings.formatters.add
-if LUAVERSION < 5.2 then
-
- addformatter(formatters,"font:name", [["'"..fontname(%s).."'"]], "local fontname = fonts.helpers.name")
- addformatter(formatters,"font:features",[["'"..sequenced(%s," ",true).."'"]],"local sequenced = table.sequenced")
-
-else
-
- addformatter(formatters,"font:name", [["'"..fontname(%s).."'"]], { fontname = helpers.name })
- addformatter(formatters,"font:features",[["'"..sequenced(%s," ",true).."'"]],{ sequenced = table.sequenced })
-
-end
+addformatter(formatters,"font:name", [["'"..fontname(%s).."'"]], { fontname = helpers.name })
+addformatter(formatters,"font:features",[["'"..sequenced(%s," ",true).."'"]],{ sequenced = table.sequenced })
-- ... like font-sfm or so
@@ -472,36 +468,40 @@ registerotffeature {
-- },
-- }
-local beforecopyingcharacters = sequencers.new {
- name = "beforecopyingcharacters",
- arguments = "target,original",
-}
+do
+
+ local beforecopyingcharacters = sequencers.new {
+ name = "beforecopyingcharacters",
+ arguments = "target,original",
+ }
-appendgroup(beforecopyingcharacters,"before") -- user
-appendgroup(beforecopyingcharacters,"system") -- private
-appendgroup(beforecopyingcharacters,"after" ) -- user
+ appendgroup(beforecopyingcharacters,"before") -- user
+ appendgroup(beforecopyingcharacters,"system") -- private
+ appendgroup(beforecopyingcharacters,"after" ) -- user
-function constructors.beforecopyingcharacters(original,target)
- local runner = beforecopyingcharacters.runner
- if runner then
- runner(original,target)
+ function constructors.beforecopyingcharacters(original,target)
+ local runner = beforecopyingcharacters.runner
+ if runner then
+ runner(original,target)
+ end
end
-end
-local aftercopyingcharacters = sequencers.new {
- name = "aftercopyingcharacters",
- arguments = "target,original",
-}
+ local aftercopyingcharacters = sequencers.new {
+ name = "aftercopyingcharacters",
+ arguments = "target,original",
+ }
-appendgroup(aftercopyingcharacters,"before") -- user
-appendgroup(aftercopyingcharacters,"system") -- private
-appendgroup(aftercopyingcharacters,"after" ) -- user
+ appendgroup(aftercopyingcharacters,"before") -- user
+ appendgroup(aftercopyingcharacters,"system") -- private
+ appendgroup(aftercopyingcharacters,"after" ) -- user
-function constructors.aftercopyingcharacters(original,target)
- local runner = aftercopyingcharacters.runner
- if runner then
- runner(original,target)
+ function constructors.aftercopyingcharacters(original,target)
+ local runner = aftercopyingcharacters.runner
+ if runner then
+ runner(original,target)
+ end
end
+
end
--[[ldx--
@@ -566,6 +566,12 @@ local function definecontext(name,t) -- can be shared
return number, t
end
+-- {a,b,c} as table (so we don' need to parse again when it gets applied)
+-- we will update this ... when we have foo={a,b,c} then we can keep the table
+
+-- \definefontfeature[demo][a={b,c}]
+-- \definefontfeature[demo][a={b=12,c={34,35}}]
+
local function presetcontext(name,parent,features) -- will go to con and shared
if features == "" and find(parent,"=",1,true) then
features = parent
@@ -575,6 +581,16 @@ local function presetcontext(name,parent,features) -- will go to con and shared
features = { }
elseif type(features) == "string" then
features = normalize_features(settings_to_hash(features))
+ -- if type(value) == "string" and find(value,"[=:]") then
+ -- local t = settings_to_hash_colon_too(value) -- clashes with foo=file:bar
+ for key, value in next, features do
+ if type(value) == "string" and find(value,"[=]") then
+ local t = settings_to_hash(value)
+ if next(t) then
+ features[key] = sequenced(normalize_features(t,true),",")
+ end
+ end
+ end
else
features = normalize_features(features)
end
@@ -584,8 +600,8 @@ local function presetcontext(name,parent,features) -- will go to con and shared
local s = setups[p]
if s then
for k, v in next, s do
--- no, as then we cannot overload: e.g. math,mathextra
--- reverted, so we only take from parent when not set
+ -- no, as then we cannot overload: e.g. math,mathextra
+ -- reverted, so we only take from parent when not set
if features[k] == nil then
features[k] = v
end
@@ -777,7 +793,8 @@ end
local function registercontext(fontnumber,extraname,option)
local extra = setups[extraname]
if extra then
- local mergedfeatures, mergedname = { }, nil
+ local mergedfeatures = { }
+ local mergedname = nil
if option < 0 then
mergedname = fontnumber .. "-" .. extraname
else
@@ -997,25 +1014,33 @@ definers.registersplit(":",colonized,"direct")
-- define (two steps)
------ space = P(" ")
------ spaces = space^0
-local leftparent = (P"(")
-local rightparent = (P")")
-local value = C((leftparent * (1-rightparent)^0 * rightparent + (1-space))^1)
-local dimension = C((space/"" + P(1))^1)
-local rest = C(P(1)^0)
-local scale_none = Cc(0)
-local scale_at = (P("at") +P("@")) * Cc(1) * spaces * dimension -- dimension
-local scale_sa = P("sa") * Cc(2) * spaces * dimension -- number
-local scale_mo = P("mo") * Cc(3) * spaces * dimension -- number
-local scale_scaled = P("scaled") * Cc(4) * spaces * dimension -- number
-local scale_ht = P("ht") * Cc(5) * spaces * dimension -- dimension
-local scale_cp = P("cp") * Cc(6) * spaces * dimension -- dimension
-
-local specialscale = { [5] = "ht", [6] = "cp" }
-
-local sizepattern = spaces * (scale_at + scale_sa + scale_mo + scale_ht + scale_cp + scale_scaled + scale_none)
-local splitpattern = spaces * value * spaces * rest
+local sizepattern, splitpattern, specialscale do
+
+ ----- space = P(" ")
+ ----- spaces = space^0
+ local leftparent = (P"(")
+ local rightparent = (P")")
+ local leftbrace = (P"{")
+ local rightbrace = (P"}")
+ local withinparents = leftparent * (1-rightparent)^0 * rightparent
+ local withinbraces = leftbrace * (1-rightbrace )^0 * rightbrace
+ local value = C((withinparents + withinbraces + (1-space))^1)
+ local dimension = C((space/"" + P(1))^1)
+ local rest = C(P(1)^0)
+ local scale_none = Cc(0)
+ local scale_at = (P("at") +P("@")) * Cc(1) * spaces * dimension -- dimension
+ local scale_sa = P("sa") * Cc(2) * spaces * dimension -- number
+ local scale_mo = P("mo") * Cc(3) * spaces * dimension -- number
+ local scale_scaled = P("scaled") * Cc(4) * spaces * dimension -- number
+ local scale_ht = P("ht") * Cc(5) * spaces * dimension -- dimension
+ local scale_cp = P("cp") * Cc(6) * spaces * dimension -- dimension
+
+ specialscale = { [5] = "ht", [6] = "cp" }
+
+ sizepattern = spaces * (scale_at + scale_sa + scale_mo + scale_ht + scale_cp + scale_scaled + scale_none)
+ splitpattern = spaces * value * spaces * rest
+
+end
function helpers.splitfontpattern(str)
local name, size = lpegmatch(splitpattern,str)
@@ -1299,7 +1324,6 @@ do -- else too many locals
local busy = false
scanners.definefont_two = function()
-
local global = scanboolean() -- \ifx\fontclass\empty\s!false\else\s!true\fi
local cs = scanstring () -- {#csname}%
local str = scanstring () -- \somefontfile
@@ -1411,6 +1435,7 @@ do -- else too many locals
specification.fallbacks = fontfallbacks
end
end
+ --
local tfmdata = definers.read(specification,size) -- id not yet known (size in spec?)
--
local lastfontid = 0
@@ -1426,15 +1451,15 @@ do -- else too many locals
-- characters[0x2007] = { width = characters[0x0030] and characters[0x0030].width or parameters.space } -- figure
-- characters[0x2008] = { width = characters[0x002E] and characters[0x002E].width or parameters.space } -- period
--
- local fallbacks = specification.fallbacks
+ local fallbacks = specification.fallbacks or ""
local mathsize = (mathsize == 1 or mathsize == 2 or mathsize == 3) and mathsize or nil -- can be unset so we test 1 2 3
- if fallbacks and fallbacks ~= "" and mathsize and not busy then
+ if fallbacks ~= "" and mathsize and not busy then
busy = true
-- We need this ugly hack in order to resolve fontnames (at the \TEX end). Originally
-- math was done in Lua after loading (plugged into aftercopying).
--
-- After tl 2017 I'll also do text fallbacks this way (although backups there are done
- -- in a completely different way.
+ -- in a completely different way.)
if trace_defining then
report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,1)
@@ -1825,7 +1850,7 @@ function mappings.loadfile(name)
if trace_mapfiles then
report_mapfiles("loading map file %a",name)
end
- pdf.mapfile(name)
+ lpdf.setmapfile(name)
loaded[name] = true
end
end
@@ -1843,17 +1868,15 @@ function mappings.loadline(how,line)
if trace_mapfiles then
report_mapfiles("processing map line %a",line)
end
- pdf.mapline(how)
+ lpdf.setmapline(how)
loaded[how] = true
end
end
function mappings.reset()
- pdf.mapfile("")
+ lpdf.setmapfile("") -- tricky ... backend related
end
-mappings.reset() -- resets the default file
-
implement {
name = "loadmapfile",
actions = mappings.loadfile,
@@ -1876,19 +1899,36 @@ implement {
-- => commands
-local function nametoslot(name)
+local pattern = P("P")
+ * (lpeg.patterns.hexdigit^4 / function(s) return tonumber(s,16) end)
+ * P(-1)
+
+local function nametoslot(name) -- also supports PXXXXX (4+ positions)
local t = type(name)
if t == "string" then
- local slot = unicodes[true][name]
+ local unic = unicodes[true]
+ local slot = unic[name]
+ if slot then
+ return slot
+ end
+ --
+ local slot = unic[gsub(name,"_"," ")] or unic[gsub(name,"_","-")] or
+ unic[gsub(name,"-"," ")] or unic[gsub(name,"-","_")] or
+ unic[gsub(name," ","_")] or unic[gsub(name," ","-")]
if slot then
return slot
end
+ --
if not aglunicodes then
aglunicodes = encodings.agl.unicodes
end
local char = characters[true]
local slot = aglunicodes[name]
- if char[slot] then
+ if slot and char[slot] then
+ return slot
+ end
+ local slot = lpegmatch(pattern,name)
+ if slot and char[slot] then
return slot
end
-- not in font
@@ -1901,14 +1941,13 @@ local function nametoslot(name)
end
end
-
local found = { }
local function descriptiontoslot(name)
local t = type(name)
if t == "string" then
-- slow
- local list = sortedkeys(chardata)
+ local list = sortedkeys(chardata) -- can be a cache with weak tables
local slot = found[name]
local char = characters[true]
if slot then
@@ -1971,13 +2010,17 @@ local function descriptiontoslot(name)
end
end
-local function indextoslot(index)
- local r = resources[true]
+local function indextoslot(font,index)
+ if not index then
+ index = font
+ font = true
+ end
+ local r = resources[font]
if r then
local indices = r.indices
if not indices then
indices = { }
- local c = characters[true]
+ local c = characters[font]
for unicode, data in next, c do
local di = data.index
if di then
@@ -2397,9 +2440,12 @@ do
return f and (f.gpos[n] or f.gsub[n])
end
+ local ctx_doifelse = commands.doifelse
+ local ctx_doif = commands.doif
+
implement {
name = "doifelsecurrentfonthasfeature",
- actions = { constructors.currentfonthasfeature, commands.doifelse },
+ actions = { constructors.currentfonthasfeature, ctx_doifelse },
arguments = "string"
}
@@ -2443,10 +2489,23 @@ do
implement {
name = "definefontfeature",
arguments = "3 strings",
- actions = presetcontext
+ actions = presetcontext,
}
implement {
+ name = "doifelsefontfeature",
+ arguments = "string",
+ actions = function(name) ctx_doifelse(contextnumber(name) > 1) end,
+ }
+
+ implement {
+ name = "doifunknownfontfeature",
+ arguments = "string",
+ actions = function(name) ctx_doif(contextnumber(name) == 0) end,
+ }
+
+
+ implement {
name = "adaptfontfeature",
arguments = "2 strings",
actions = adaptcontext
@@ -2602,8 +2661,6 @@ do
local unsetvalue = attributes.unsetvalue
- local traverse_char = nuts.traverse_char
-
local a_color = attributes.private('color')
local a_colormodel = attributes.private('colormodel')
local a_state = attributes.private('state')
@@ -2627,11 +2684,14 @@ do
[states.pstf] = "font:5",
}
+ -- todo: traversers
+ -- todo: check attr_list so that we can use the same .. helper: setcolorattr
+
local function markstates(head)
if head then
head = tonut(head)
local model = getattr(head,a_colormodel) or 1
- for glyph in traverse_char(head) do
+ for glyph in nextchar, head do
local a = getprop(glyph,a_state)
if a then
local name = colornames[a]
@@ -2682,8 +2742,8 @@ do
function methods.nocolor(head,font,attr)
- for n in traverse_char(head) do
- if not font or getfont(n) == font then
+ for n, c, f in nextchar, head do
+ if not font or f == font then
setattr(n,a_color,unsetvalue)
end
end
@@ -2708,9 +2768,13 @@ implement {
arguments = "string",
}
-local list = storage.shared.bodyfontsizes or { }
+local sharedstorage = storage.shared
-storage.shared.bodyfontsizes = list
+local list = sharedstorage.bodyfontsizes or { }
+local unknown = sharedstorage.unknownbodyfontsizes or { }
+
+sharedstorage.bodyfontsizes = list
+sharedstorage.unknownbodyfontsizes = unknown
implement {
name = "registerbodyfontsize",
@@ -2720,6 +2784,17 @@ implement {
end
}
+interfaces.implement {
+ name = "registerunknownbodysize",
+ arguments = "string",
+ actions = function(size)
+ if not unknown[size] then
+ interfaces.showmessage("fonts",14,size)
+ end
+ unknown[size] = true
+ end,
+}
+
implement {
name = "getbodyfontsizes",
arguments = "string",
@@ -2873,6 +2948,12 @@ end
-- for the font manual
+statistics.register("body font sizes", function()
+ if next(unknown) then
+ return formatters["defined: % t, undefined: % t"](sortedkeys(list),sortedkeys(unknown))
+ end
+end)
+
statistics.register("used fonts",function()
if trace_usage then
local filename = file.nameonly(environment.jobname) .. "-fonts-usage.lua"
@@ -3018,79 +3099,285 @@ end
-- for the moment here (and not in font-con.lua):
-local identical = table.identical
-local copy = table.copy
-local fontdata = fonts.hashes.identifiers
-local addcharacters = font.addcharacters
-
--- This helper is mostly meant to add last-resort (virtual) characters
--- or runtime generated fonts (so we forget about features and such). It
--- will probably take a while before it get used.
-
-local trace_adding = false
-local report_adding = logs.reporter("fonts","add characters")
-
-trackers.register("fonts.addcharacters",function(v) trace_adding = v end)
-
-if addcharacters then
-
- function fonts.constructors.addcharacters(id,list)
- local newchar = list.characters
- if newchar then
- local data = fontdata[id]
- local newfont = list.fonts
- local oldchar = data.characters
- local oldfont = data.fonts
- addcharacters(id, {
- characters = newchar,
- fonts = newfont,
- nomath = not data.properties.hasmath,
- })
- -- this is just for tracing, as the assignment only uses the fonts list
- -- and doesn't store it otherwise
- if newfont then
- if oldfont then
- local oldn = #oldfont
- local newn = #newfont
- for n=1,newn do
- local ok = false
- local nf = newfont[n]
- for o=1,oldn do
- if identical(nf,oldfont[o]) then
- ok = true
- break
+do
+
+ local identical = table.identical
+ local copy = table.copy
+ local fontdata = fonts.hashes.identifiers
+ local addcharacters = font.addcharacters
+
+ -- This helper is mostly meant to add last-resort (virtual) characters
+ -- or runtime generated fonts (so we forget about features and such). It
+ -- will probably take a while before it get used.
+
+ local trace_adding = false
+ local report_adding = logs.reporter("fonts","add characters")
+
+ trackers.register("fonts.addcharacters",function(v) trace_adding = v end)
+
+ if addcharacters then
+
+ function fonts.constructors.addcharacters(id,list)
+ local newchar = list.characters
+ if newchar then
+ local data = fontdata[id]
+ local newfont = list.fonts
+ local oldchar = data.characters
+ local oldfont = data.fonts
+ addcharacters(id, {
+ characters = newchar,
+ fonts = newfont,
+ nomath = not data.properties.hasmath,
+ })
+ -- this is just for tracing, as the assignment only uses the fonts list
+ -- and doesn't store it otherwise
+ if newfont then
+ if oldfont then
+ local oldn = #oldfont
+ local newn = #newfont
+ for n=1,newn do
+ local ok = false
+ local nf = newfont[n]
+ for o=1,oldn do
+ if identical(nf,oldfont[o]) then
+ ok = true
+ break
+ end
+ end
+ if not ok then
+ oldn = oldn + 1
+ oldfont[oldn] = newfont[i]
end
end
- if not ok then
- oldn = oldn + 1
- oldfont[oldn] = newfont[i]
- end
+ else
+ data.fonts = newfont
end
- else
- data.fonts = newfont
end
- end
- -- this is because we need to know what goes on and also might
- -- want to access character data
- for u, c in next, newchar do
- if trace_adding then
- report_adding("adding character %U to font %!font:name!",u,id)
+ -- this is because we need to know what goes on and also might
+ -- want to access character data
+ for u, c in next, newchar do
+ if trace_adding then
+ report_adding("adding character %U to font %!font:name!",u,id)
+ end
+ oldchar[u] = c
end
- oldchar[u] = c
end
end
+
+ else
+ function fonts.constructors.addcharacters(id,list)
+ report_adding("adding characters to %!font:name! is not yet supported",id)
+ end
end
-else
- function fonts.constructors.addcharacters(id,list)
- report_adding("adding characters to %!font:name! is not yet supported",id)
+ implement {
+ name = "addfontpath",
+ arguments = "string",
+ actions = function(list)
+ names.addruntimepath(settings_to_array(list))
+ end
+ }
+
+end
+
+-- moved here
+
+do
+
+ local family_font = node.family_font
+ local new_glyph = nodes.pool.glyph
+ local fontproperties = fonts.hashes.properties
+
+ local function getprivateslot(id,name)
+ if not name then
+ name = id
+ id = currentfont()
+ end
+ local properties = fontproperties[id]
+ local privates = properties and properties.privates
+ return privates and privates[name]
+ end
+
+ local function getprivatenode(tfmdata,name)
+ if type(tfmdata) == "number" then
+ tfmdata = fontdata[tfmdata]
+ end
+ local properties = tfmdata.properties
+ local font = properties.id
+ local slot = getprivateslot(font,name)
+ if slot then
+ -- todo: set current attribibutes
+ local char = tfmdata.characters[slot]
+ local tonode = char.tonode
+ if tonode then
+ return tonode(font,char)
+ else
+ return new_glyph(font,slot)
+ end
+ end
+ end
+
+ local function getprivatecharornode(tfmdata,name)
+ if type(tfmdata) == "number" then
+ tfmdata = fontdata[tfmdata]
+ end
+ local properties = tfmdata.properties
+ local font = properties.id
+ local slot = getprivateslot(font,name)
+ if slot then
+ -- todo: set current attributes
+ local char = tfmdata.characters[slot]
+ local tonode = char.tonode
+ if tonode then
+ return "node", tonode(tfmdata,char)
+ else
+ return "char", slot
+ end
+ end
end
+
+ helpers.getprivateslot = getprivateslot
+ helpers.getprivatenode = getprivatenode
+ helpers.getprivatecharornode = getprivatecharornode
+
+ implement {
+ name = "getprivatechar",
+ arguments = "string",
+ actions = function(name)
+ local p = getprivateslot(name)
+ if p then
+ context(utfchar(p))
+ end
+ end
+ }
+
+ implement {
+ name = "getprivatemathchar",
+ arguments = "string",
+ actions = function(name)
+ local p = getprivateslot(family_font(0),name)
+ if p then
+ context(utfchar(p))
+ end
+ end
+ }
+
+ implement {
+ name = "getprivateslot",
+ arguments = "string",
+ actions = function(name)
+ local p = getprivateslot(name)
+ if p then
+ context(p)
+ end
+ end
+ }
+
end
-implement {
- name = "addfontpath",
- arguments = "string",
- actions = function(list)
- names.addruntimepath(settings_to_array(list))
+-- handy, for now here:
+
+function fonts.helpers.collectanchors(tfmdata)
+
+ local resources = tfmdata.resources -- todo: use shared
+
+ if not resources or resources.anchors then
+ return resources.anchors
end
-}
+
+ local anchors = { }
+
+ local function set(unicode,target,class,anchor)
+ local a = anchors[unicode]
+ if not a then
+ anchors[unicode] = { [target] = { anchor } }
+ return
+ end
+ local t = a[target]
+ if not t then
+ a[target] = { anchor }
+ return
+ end
+ local x = anchor[1]
+ local y = anchor[2]
+ for k, v in next, t do
+ if v[1] == x and v[2] == y then
+ return
+ end
+ end
+ t[#t+1] = anchor
+ end
+
+ local function getanchors(steps,target)
+ for i=1,#steps do
+ local step = steps[i]
+ local coverage = step.coverage
+ for unicode, data in next, coverage do
+ local class = data[1]
+ local anchor = data[2]
+ if anchor[1] ~= 0 or anchor[2] ~= 0 then
+ set(unicode,target,class,anchor)
+ end
+ end
+ end
+ end
+
+ local function getcursives(steps)
+ for i=1,#steps do
+ local step = steps[i]
+ local coverage = step.coverage
+ for unicode, data in next, coverage do
+ local class = data[1]
+ local en = data[2]
+ local ex = data[3]
+ if en then
+ set(unicode,"entry",class,en)
+ end
+ if ex then
+ set(unicode,"exit", class,ex)
+ end
+ end
+ end
+ end
+
+ local function collect(list)
+ if list then
+ for i=1,#list do
+ local entry = list[i]
+ local steps = entry.steps
+ local kind = entry.type
+ if kind == "gpos_mark2mark" then
+ getanchors(steps,"mark")
+ elseif kind == "gpos_mark2base" then
+ getanchors(steps,"base")
+ elseif kind == "gpos_mark2ligature" then
+ getanchors(steps,"ligature")
+ elseif kind == "gpos_cursive" then
+ getcursives(steps)
+ end
+ end
+ end
+ end
+
+ collect(resources.sequences)
+ collect(resources.sublookups)
+
+ local function sorter(a,b)
+ if a[1] == b[1] then
+ return a[2] < b[2]
+ else
+ return a[1] < b[1]
+ end
+ end
+
+ for unicode, old in next, anchors do
+ for target, list in next, old do
+ sort(list,sorter)
+ end
+ end
+
+ resources.anchors = anchors
+
+ return anchors
+
+end
diff --git a/tex/context/base/mkiv/font-def.lua b/tex/context/base/mkiv/font-def.lua
index 97d25f180..f3d0f8187 100644
--- a/tex/context/base/mkiv/font-def.lua
+++ b/tex/context/base/mkiv/font-def.lua
@@ -80,53 +80,6 @@ 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, "" -- not so nice
-
-local P, C, S, Cc = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc
-
-local left = P("(")
-local right = P(")")
-local colon = P(":")
-local space = P(" ")
-
-definers.defaultlookup = "file"
-
-local prefixpattern = P(false)
-
-local function addspecifier(symbol)
- splitspecifiers = splitspecifiers .. symbol
- local method = S(splitspecifiers)
- local lookup = C(prefixpattern) * colon
- local sub = left * C(P(1-left-right-method)^1) * right
- local specification = C(method) * C(P(1)^1)
- local name = C((1-sub-specification)^1)
- splitter = P((lookup + Cc("")) * name * (sub + Cc("")) * (specification + Cc("")))
-end
-
-local function addlookup(str,default)
- prefixpattern = prefixpattern + P(str)
-end
-
-definers.addlookup = addlookup
-
-addlookup("file")
-addlookup("name")
-addlookup("spec")
-
-local function getspecification(str)
- return lpegmatch(splitter,str or "") -- weird catch
-end
-
-definers.getspecification = getspecification
-
-function definers.registersplit(symbol,action,verbosename)
- addspecifier(symbol)
- variants[symbol] = action
- if verbosename then
- variants[verbosename] = action
- end
-end
-
local function makespecification(specification,lookup,name,sub,method,detail,size)
size = size or 655360
if not lookup or lookup == "" then
@@ -151,13 +104,65 @@ local function makespecification(specification,lookup,name,sub,method,detail,siz
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 makespecification(specification, lookup, name, sub, method, detail, size)
+if context then
+
+ local splitter, splitspecifiers = nil, "" -- not so nice
+
+ local P, C, S, Cc, Cs = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc, lpeg.Cs
+
+ local left = P("(")
+ local right = P(")")
+ local colon = P(":")
+ local space = P(" ")
+ local lbrace = P("{")
+ local rbrace = P("}")
+
+ definers.defaultlookup = "file"
+
+ local prefixpattern = P(false)
+
+ local function addspecifier(symbol)
+ splitspecifiers = splitspecifiers .. symbol
+ local method = S(splitspecifiers)
+ local lookup = C(prefixpattern) * colon
+ local sub = left * C(P(1-left-right-method)^1) * right
+ local specification = C(method) * C(P(1)^1)
+ local name = Cs((lbrace/"") * (1-rbrace)^1 * (rbrace/"") + (1-sub-specification)^1)
+ splitter = P((lookup + Cc("")) * name * (sub + Cc("")) * (specification + Cc("")))
+ end
+
+ local function addlookup(str)
+ prefixpattern = prefixpattern + P(str)
+ end
+
+ definers.addlookup = addlookup
+
+ addlookup("file")
+ addlookup("name")
+ addlookup("spec")
+
+ local function getspecification(str)
+ return lpegmatch(splitter,str or "") -- weird catch
+ end
+
+ definers.getspecification = getspecification
+
+ function definers.registersplit(symbol,action,verbosename)
+ addspecifier(symbol)
+ variants[symbol] = action
+ if verbosename then
+ variants[verbosename] = action
+ end
+ end
+
+ function definers.analyze(specification, size)
+ -- can be optimized with locals
+ local lookup, name, sub, method, detail = getspecification(specification or "")
+ return makespecification(specification, lookup, name, sub, method, detail, size)
+ end
+
end
--[[ldx--
@@ -203,9 +208,9 @@ function resolvers.name(specification)
features.normal = normal
end
normal.instance = instance
- if not callbacks.supported.glyph_stream_provider then
- normal.variableshapes = true -- for the moment
- end
+ -- if not callbacks.supported.glyph_stream_provider then
+ -- normal.variableshapes = true -- for the moment
+ -- end
end
--
local suffix = lower(suffixonly(resolved))
@@ -335,7 +340,7 @@ local function checkfeatures(tfmdata)
for script, languages in next, scripts do
if languages["*"] then
-- ok
- elseif not languages[usedlanguage] then
+ elseif context and not languages[usedlanguage] then
report_defining("font %!font:name!, feature %a, script %a, no language %a",
tfmdata,feature,script,usedlanguage)
end
@@ -355,7 +360,7 @@ local function checkfeatures(tfmdata)
if not languages["*"] then
for i=1,#foundlanguages do
local language = foundlanguages[i]
- if not languages[language] then
+ if context and not languages[language] then
report_defining("font %!font:name!, feature %a, script %a, no language %a",
tfmdata,feature,script,language)
end
@@ -377,6 +382,7 @@ function definers.loadfont(specification)
-- todo: also hash by instance / factors
local tfmdata = loadedfonts[hash] -- hashes by size !
if not tfmdata then
+ -- normally context will not end up here often (if so there is an issue somewhere)
local forced = specification.forced or ""
if forced ~= "" then
local reader = readers[lower(forced)] -- normally forced is already lowered
diff --git a/tex/context/base/mkiv/font-dsp.lua b/tex/context/base/mkiv/font-dsp.lua
index 02e5a7df6..046ba2850 100644
--- a/tex/context/base/mkiv/font-dsp.lua
+++ b/tex/context/base/mkiv/font-dsp.lua
@@ -51,7 +51,10 @@ if not modules then modules = { } end modules ['font-dsp'] = {
-- All this packing in the otf format is somewhat obsessive as nowadays 4K resolution
-- multi-gig videos pass through our networks and storage and memory is abundant.
-local next, type = next, type
+-- Although we use a few table readers there i sno real gain in there (apart from having
+-- less code. After all there are often not that many demanding features.
+
+local next, type, tonumber = next, type, tonumber
local band = bit32.band
local extract = bit32.extract
local bor = bit32.bor
@@ -68,12 +71,13 @@ local reversed = table.reversed
local sort = table.sort
local insert = table.insert
local round = math.round
-local lpegmatch = lpeg.match
+local settings_to_hash = utilities.parsers.settings_to_hash_colon_too
local setmetatableindex = table.setmetatableindex
local formatters = string.formatters
local sortedkeys = table.sortedkeys
local sortedhash = table.sortedhash
+local sequenced = table.sequenced
local report = logs.reporter("otf reader")
@@ -82,10 +86,11 @@ local streamreader = readers.streamreader
local setposition = streamreader.setposition
local getposition = streamreader.getposition
-local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
-local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer
+local readuinteger = streamreader.readcardinal1
+local readushort = streamreader.readcardinal2
+local readulong = streamreader.readcardinal4
local readinteger = streamreader.readinteger1
-local readshort = streamreader.readinteger2 -- 16-bit signed integer
+local readshort = streamreader.readinteger2
local readstring = streamreader.readstring
local readtag = streamreader.readtag
local readbytes = streamreader.readbytes
@@ -93,9 +98,41 @@ local readfixed = streamreader.readfixed4
local read2dot14 = streamreader.read2dot14
local skipshort = streamreader.skipshort
local skipbytes = streamreader.skip
-local readfword = readshort
local readbytetable = streamreader.readbytetable
local readbyte = streamreader.readbyte
+local readcardinaltable = streamreader.readcardinaltable
+local readintegertable = streamreader.readintegertable
+local readfword = readshort
+
+local short = 2
+local ushort = 2
+local ulong = 4
+
+directives.register("fonts.streamreader",function()
+
+ streamreader = utilities.streams
+
+ setposition = streamreader.setposition
+ getposition = streamreader.getposition
+ readuinteger = streamreader.readcardinal1
+ readushort = streamreader.readcardinal2
+ readulong = streamreader.readcardinal4
+ readinteger = streamreader.readinteger1
+ readshort = streamreader.readinteger2
+ readstring = streamreader.readstring
+ readtag = streamreader.readtag
+ readbytes = streamreader.readbytes
+ readfixed = streamreader.readfixed4
+ read2dot14 = streamreader.read2dot14
+ skipshort = streamreader.skipshort
+ skipbytes = streamreader.skip
+ readbytetable = streamreader.readbytetable
+ readbyte = streamreader.readbyte
+ readcardinaltable = streamreader.readcardinaltable
+ readintegertable = streamreader.readintegertable
+ readfword = readshort
+
+end)
local gsubhandlers = { }
local gposhandlers = { }
@@ -196,39 +233,6 @@ local read_integer = {
streamreader.readinteger4,
}
--- using helpers doesn't make much sense, subtle differences
---
--- local function readushortarray(f,n)
--- local t = { }
--- for i=1,n do
--- t[i] = readushort(f)
--- end
--- return t
--- end
---
--- local function readulongarray(f,n)
--- local t = { }
--- for i=1,n do
--- t[i] = readulong(f)
--- end
--- return t
--- end
---
--- local function readushortarray(f,target,first,size)
--- if not size then
--- for i=1,size do
--- target[i] = readushort(f)
--- end
--- else
--- for i=1,size do
--- target[first+i] = readushort(f)
--- end
--- end
--- return target
--- end
---
--- so we get some half helper - half non helper mix then
-
-- Traditionally we use these unique names (so that we can flatten the lookup list
-- (we create subsets runtime) but I will adapt the old code to newer names.
@@ -300,30 +304,16 @@ end)
-- wght:400,wdth:100,ital:1
--- local names = table.setmetatableindex ( {
--- weight = "wght",
--- width = "wdth",
--- italic = "ital",
--- }, "self")
-
--- todo: spaces in name but not before :
-
-local pattern = lpeg.Cf (
- lpeg.Ct("") *
- lpeg.Cg (
- --(lpeg.R("az")^1/names) * lpeg.S(" :") *
- lpeg.C((lpeg.R("az","09")+lpeg.P(" "))^1) * lpeg.S(" :=") *
- (lpeg.patterns.number/tonumber) * lpeg.S(" ,")^0
- )^1, rawset
-)
+local function axistofactors(str)
+ local t = settings_to_hash(str)
+ for k, v in next, t do
+ t[k] = tonumber(v) or v -- this also normalizes numbers itself
+ end
+ return t
+end
local hash = table.setmetatableindex(function(t,k)
- local v = lpegmatch(pattern,k)
- local t = { }
- for k, v in sortedhash(v) do
- t[#t+1] = k .. "=" .. v
- end
- v = concat(t,",")
+ local v = sequenced(axistofactors(k),",")
t[k] = v
return v
end)
@@ -340,10 +330,6 @@ function helpers.normalizedaxis(str)
return hash[str] or str
end
-local function axistofactors(str)
- return lpegmatch(pattern,str)
-end
-
-- contradicting spec ... (signs) so i'll check it and fix it once we have
-- proper fonts
@@ -498,10 +484,7 @@ local function readvariationdata(f,storeoffset,factors) -- store
local format = readushort(f)
local regionoffset = storeoffset + readulong(f)
local nofdeltadata = readushort(f)
- local deltadata = { }
- for i=1,nofdeltadata do
- deltadata[i] = readulong(f)
- end
+ local deltadata = readcardinaltable(f,nofdeltadata,ulong)
-- regions
setposition(f,regionoffset)
local nofaxis = readushort(f)
@@ -532,10 +515,7 @@ local function readvariationdata(f,storeoffset,factors) -- store
end
-- we could test before and save a for
for i=1,nofdeltasets do
- local t = { } -- newtable
- for i=1,nofshorts do
- t[i] = readshort(f)
- end
+ local t = readintegertable(f,nofshorts,short)
for i=nofshorts+1,nofregions do
t[i] = readinteger(f)
end
@@ -560,21 +540,32 @@ helpers.readvariationdata = readvariationdata
local function readcoverage(f,offset,simple)
setposition(f,offset)
local coverageformat = readushort(f)
- local coverage = { }
if coverageformat == 1 then
local nofcoverage = readushort(f)
if simple then
- for i=1,nofcoverage do
- coverage[i] = readushort(f)
+ -- often 1 or 2
+ if nofcoverage == 1 then
+ return { readushort(f) }
+ elseif nofcoverage == 2 then
+ return { readushort(f), readushort(f) }
+ else
+ return readcardinaltable(f,nofcoverage,ushort)
end
+ elseif nofcoverage == 1 then
+ return { [readushort(f)] = 0 }
+ elseif nofcoverage == 2 then
+ return { [readushort(f)] = 0, [readushort(f)] = 1 }
else
+ local coverage = { }
for i=0,nofcoverage-1 do
coverage[readushort(f)] = i -- index in record
end
+ return coverage
end
elseif coverageformat == 2 then
local nofranges = readushort(f)
- local n = simple and 1 or 0 -- needs checking
+ local coverage = { }
+ local n = simple and 1 or 0 -- needs checking
for i=1,nofranges do
local firstindex = readushort(f)
local lastindex = readushort(f)
@@ -591,10 +582,11 @@ local function readcoverage(f,offset,simple)
end
end
end
+ return coverage
else
report("unknown coverage format %a ",coverageformat)
+ return { }
end
- return coverage
end
local function readclassdef(f,offset,preset)
@@ -828,23 +820,17 @@ local function readfirst(f,offset)
return { readushort(f) }
end
-local function readarray(f,offset,first)
+-- quite often 0, 1, 2
+
+function readarray(f,offset)
if offset then
setposition(f,offset)
end
local n = readushort(f)
- if first then
- local t = { first }
- for i=2,n do
- t[i] = readushort(f)
- end
- return t, n
+ if n == 1 then
+ return { readushort(f) }, 1
elseif n > 0 then
- local t = { }
- for i=1,n do
- t[i] = readushort(f)
- end
- return t, n
+ return readcardinaltable(f,n,ushort), n
end
end
@@ -1023,8 +1009,9 @@ local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,n
rules = rules,
}
elseif subtype == 3 then
- local current = readarray(f)
+ local nofglyphs = readushort(f)
local noflookups = readushort(f)
+ local current = readcardinaltable(f,nofglyphs,ushort)
local lookups = readlookuparray(f,noflookups,#current)
current = readcoveragearray(f,tableoffset,current,true)
return {
@@ -1231,7 +1218,7 @@ function gsubhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofg
local delta = readshort(f) -- can be negative
local coverage = readcoverage(f,tableoffset+coverage) -- not simple as we need to set key/value anyway
for index in next, coverage do
- local newindex = index + delta
+ local newindex = (index + delta) % 65536 -- modulo is new in 1.8.3
if index > nofglyphs or newindex > nofglyphs then
report("invalid index in %s format %i: %i -> %i (max %i)","single",subtype,index,newindex,nofglyphs)
coverage[index] = nil
@@ -1245,10 +1232,7 @@ function gsubhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofg
elseif subtype == 2 then -- in streamreader a seek and fetch is faster than a temp table
local coverage = readushort(f)
local nofreplacements = readushort(f)
- local replacements = { }
- for i=1,nofreplacements do
- replacements[i] = readushort(f)
- end
+ local replacements = readcardinaltable(f,nofreplacements,ushort)
local coverage = readcoverage(f,tableoffset + coverage) -- not simple as we need to set key/value anyway
for index, newindex in next, coverage do
newindex = newindex + 1
@@ -1276,18 +1260,10 @@ local function sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyp
if subtype == 1 then
local coverage = readushort(f)
local nofsequence = readushort(f)
- local sequences = { }
- for i=1,nofsequence do
- sequences[i] = readushort(f)
- end
+ local sequences = readcardinaltable(f,nofsequence,ushort)
for i=1,nofsequence do
setposition(f,tableoffset + sequences[i])
- local n = readushort(f)
- local s = { }
- for i=1,n do
- s[i] = readushort(f)
- end
- sequences[i] = s
+ sequences[i] = readcardinaltable(f,readushort(f),ushort)
end
local coverage = readcoverage(f,tableoffset + coverage)
for index, newindex in next, coverage do
@@ -1322,19 +1298,20 @@ function gsubhandlers.ligature(f,fontdata,lookupid,lookupoffset,offset,glyphs,no
if subtype == 1 then
local coverage = readushort(f)
local nofsets = readushort(f)
- local ligatures = { }
- for i=1,nofsets do
- ligatures[i] = readushort(f)
- end
+ local ligatures = readcardinaltable(f,nofsets,ushort)
for i=1,nofsets do
local offset = lookupoffset + offset + ligatures[i]
setposition(f,offset)
local n = readushort(f)
- local l = { }
- for i=1,n do
- l[i] = offset + readushort(f)
+ if n == 1 then
+ ligatures[i] = { offset + readushort(f) }
+ else
+ local l = { }
+ for i=1,n do
+ l[i] = offset + readushort(f)
+ end
+ ligatures[i] = l
end
- ligatures[i] = l
end
local coverage = readcoverage(f,tableoffset + coverage)
for index, newindex in next, coverage do
@@ -1982,10 +1959,15 @@ do
local parameters = readushort(f) -- feature.parameters
local noflookups = readushort(f)
if noflookups > 0 then
- local lookups = { }
+-- local lookups = { }
+-- feature.lookups = lookups
+-- for j=1,noflookups do
+-- lookups[j] = readushort(f) + 1
+-- end
+ local lookups = readcardinaltable(f,noflookups,ushort)
feature.lookups = lookups
for j=1,noflookups do
- lookups[j] = readushort(f) + 1
+ lookups[j] = lookups[j] + 1
end
end
if parameters > 0 then
@@ -2001,11 +1983,8 @@ do
local function readlookups(f,lookupoffset,lookuptypes,featurehash,featureorder)
setposition(f,lookupoffset)
- local lookups = { }
local noflookups = readushort(f)
- for i=1,noflookups do
- lookups[i] = readushort(f)
- end
+ local lookups = readcardinaltable(f,noflookups,ushort)
for lookupid=1,noflookups do
local offset = lookups[lookupid]
setposition(f,lookupoffset+offset)
@@ -2237,7 +2216,7 @@ do
report_issue(i,what,sequence,"no")
elseif not next(rlookups) then
-- can be ok as it aborts a chain sequence
- report_issue(i,what,sequence,"empty")
+ -- report_issue(i,what,sequence,"empty")
rule.lookups = nil
else
-- we can have holes in rlookups flagged false and we can have multiple lookups
@@ -2296,9 +2275,7 @@ do
end
end
end
--- report("before : % t",rlookups[index])
rlookups[index] = noffound > 0 and found or false
--- report("after : % t",rlookups[index])
else
rlookups[index] = false
end
@@ -2322,7 +2299,7 @@ do
local function loadvariations(f,fontdata,variationsoffset,lookuptypes,featurehash,featureorder)
setposition(f,variationsoffset)
- local version = readulong(f)
+ local version = readulong(f) -- two times readushort
local nofrecords = readulong(f)
local records = { }
for i=1,nofrecords do
@@ -2338,11 +2315,12 @@ do
record.condition = nil
record.matchtype = "always"
else
- setposition(f,variationsoffset+offset)
+ local offset = variationsoffset+offset
+ setposition(f,offset)
local nofconditions = readushort(f)
local conditions = { }
for i=1,nofconditions do
- conditions[i] = variationsoffset+offset+readulong(f)
+ conditions[i] = offset + readulong(f)
end
record.conditions = conditions
record.matchtype = "condition"
@@ -2385,10 +2363,7 @@ do
setposition(f,tableoffset)
local parameters = readulong(f) -- feature parameters
local noflookups = readushort(f)
- local lookups = { }
- for i=1,noflookups do
- lookups[i] = readushort(f) -- not sure what to do with these
- end
+ local lookups = readcardinaltable(f,noflookups,ushort) -- not sure what to do with these
-- todo : resolve to proper lookups
record.substitutions = lookups
end
@@ -2449,7 +2424,7 @@ do
elseif specification.globalkerns then
name = "globalkern"
else
- report("ignoring global kern table using gpos kern feature")
+ report("ignoring global kern table, using gpos kern feature")
return
end
setposition(f,datatable.offset)
@@ -2611,10 +2586,7 @@ function readers.gdef(f,fontdata,specification)
local format = readushort(f)
if format == 1 then
local nofsets = readushort(f)
- local sets = { }
- for i=1,nofsets do
- sets[i] = readulong(f)
- end
+ local sets = readcardinaltable(f,nofsets,ulong)
for i=1,nofsets do
local offset = sets[i]
if offset ~= 0 then
@@ -2851,14 +2823,8 @@ local function readmathvariants(f,fontdata,offset)
local hcoverage = readushort(f)
local vnofglyphs = readushort(f)
local hnofglyphs = readushort(f)
- local vconstruction = { }
- local hconstruction = { }
- for i=1,vnofglyphs do
- vconstruction[i] = readushort(f)
- end
- for i=1,hnofglyphs do
- hconstruction[i] = readushort(f)
- end
+ local vconstruction = readcardinaltable(f,vnofglyphs,ushort)
+ local hconstruction = readcardinaltable(f,hnofglyphs,ushort)
fontdata.mathconstants.MinConnectorOverlap = minoverlap
@@ -3033,10 +2999,7 @@ function readers.cpal(f,fontdata,specification)
local nofcolorrecords = readushort(f)
local firstcoloroffset = readulong(f)
local colorrecords = { }
- local palettes = { }
- for i=1,nofpalettes do
- palettes[i] = readushort(f)
- end
+ local palettes = readcardinaltable(f,nofpalettes,ushort)
if version == 1 then
-- used for guis
local palettettypesoffset = readulong(f)
@@ -3109,183 +3072,324 @@ function readers.sbix(f,fontdata,specification)
for i=1,nofstrikes do
strikes[i] = readulong(f)
end
- -- if true then
- local shapes = { }
- local done = 0
- for i=1,nofstrikes do
- local strikeoffset = strikes[i] + tableoffset
- setposition(f,strikeoffset)
- strikes[i] = {
- ppem = readushort(f),
- ppi = readushort(f),
- offset = strikeoffset
+ local shapes = { }
+ local done = 0
+ for i=1,nofstrikes do
+ local strikeoffset = strikes[i] + tableoffset
+ setposition(f,strikeoffset)
+ strikes[i] = {
+ ppem = readushort(f),
+ ppi = readushort(f),
+ offset = strikeoffset
+ }
+ end
+ -- highest first
+ sort(strikes,function(a,b)
+ if b.ppem == a.ppem then
+ return b.ppi < a.ppi
+ else
+ return b.ppem < a.ppem
+ end
+ end)
+ local glyphs = { }
+ for i=1,nofstrikes do
+ local strike = strikes[i]
+ local strikeppem = strike.ppem
+ local strikeppi = strike.ppi
+ local strikeoffset = strike.offset
+ setposition(f,strikeoffset)
+ for i=0,nofglyphs do
+ glyphs[i] = readulong(f)
+ end
+ local glyphoffset = glyphs[0]
+ for i=0,nofglyphs-1 do
+ local nextoffset = glyphs[i+1]
+ if not shapes[i] then
+ local datasize = nextoffset - glyphoffset
+ if datasize > 0 then
+ setposition(f,strikeoffset + glyphoffset)
+ shapes[i] = {
+ x = readshort(f),
+ y = readshort(f),
+ tag = readtag(f), -- maybe for tracing
+ data = readstring(f,datasize-8),
+ ppem = strikeppem, -- not used, for tracing
+ ppi = strikeppi, -- not used, for tracing
+ }
+ done = done + 1
+ if done == nofglyphs then
+ break
+ end
+ end
+ end
+ glyphoffset = nextoffset
+ end
+ end
+ fontdata.pngshapes = shapes
+ end
+end
+
+-- Another bitmap (so not that useful) format. But Luigi found a font that
+-- has them , so ...
+
+do
+
+ local function getmetrics(f)
+ return {
+ ascender = readinteger(f),
+ descender = readinteger(f),
+ widthmax = readuinteger(f),
+ caretslopedumerator = readinteger(f),
+ caretslopedenominator = readinteger(f),
+ caretoffset = readinteger(f),
+ minorigin = readinteger(f),
+ minadvance = readinteger(f),
+ maxbefore = readinteger(f),
+ minafter = readinteger(f),
+ pad1 = readinteger(f),
+ pad2 = readinteger(f),
+ }
+ end
+
+ -- bad names
+
+ local function getbigmetrics(f)
+ -- bigmetrics, maybe just skip 9 bytes
+ return {
+ height = readuinteger(f),
+ width = readuinteger(f),
+ horiBearingX = readinteger(f),
+ horiBearingY = readinteger(f),
+ horiAdvance = readuinteger(f),
+ vertBearingX = readinteger(f),
+ vertBearingY = readinteger(f),
+ vertAdvance = readuinteger(f),
+ }
+ end
+
+ local function getsmallmetrics(f)
+ -- smallmetrics, maybe just skip 5 bytes
+ return {
+ height = readuinteger(f),
+ width = readuinteger(f),
+ bearingX = readinteger(f),
+ bearingY = readinteger(f),
+ advance = readuinteger(f),
+ }
+ end
+
+ function readers.cblc(f,fontdata,specification)
+ -- should we delay this ?
+ local ctdttableoffset = gotodatatable(f,fontdata,"cbdt",specification.glyphs)
+ if not ctdttableoffset then
+ return
+ end
+ local cblctableoffset = gotodatatable(f,fontdata,"cblc",specification.glyphs)
+ if cblctableoffset then
+ local majorversion = readushort(f)
+ local minorversion = readushort(f)
+ local nofsizetables = readulong(f)
+ local sizetables = { }
+ local shapes = { }
+ local subtables = { }
+ for i=1,nofsizetables do
+ sizetables[i] = {
+ subtables = readulong(f),
+ indexsize = readulong(f),
+ nofsubtables = readulong(f),
+ colorref = readulong(f),
+ hormetrics = getmetrics(f),
+ vermetrics = getmetrics(f),
+ firstindex = readushort(f),
+ lastindex = readushort(f),
+ ppemx = readbyte(f),
+ ppemy = readbyte(f),
+ bitdepth = readbyte(f),
+ flags = readbyte(f),
}
end
- -- highest first
- sort(strikes,function(a,b)
- if b.ppem == a.ppem then
- return b.ppi < a.ppi
+ sort(sizetables,function(a,b)
+ if b.ppemx == a.ppemx then
+ return b.bitdepth < a.bitdepth
else
- return b.ppem < a.ppem
+ return b.ppemx < a.ppemx
end
end)
- local glyphs = { }
- for i=1,nofstrikes do
- local strike = strikes[i]
- local strikeppem = strike.ppem
- local strikeppi = strike.ppi
- local strikeoffset = strike.offset
- setposition(f,strikeoffset)
- for i=0,nofglyphs do
- glyphs[i] = readulong(f)
+ for i=1,nofsizetables do
+ local s = sizetables[i]
+ local d = false
+ for j=s.firstindex,s.lastindex do
+ if not shapes[j] then
+ shapes[j] = i
+ d = true
+ end
end
- local glyphoffset = glyphs[0]
- for i=0,nofglyphs-1 do
- local nextoffset = glyphs[i+1]
- if not shapes[i] then
- local datasize = nextoffset - glyphoffset
- if datasize > 0 then
- setposition(f,strikeoffset + glyphoffset)
- shapes[i] = {
- x = readshort(f),
- y = readshort(f),
- tag = readtag(f), -- maybe for tracing
- data = readstring(f,datasize-8),
- ppem = strikeppem, -- not used, for tracing
- ppi = strikeppi, -- not used, for tracing
- }
- done = done + 1
- if done == nofglyphs then
- break
+ if d then
+ s.used = true
+ end
+ end
+ for i=1,nofsizetables do
+ local s = sizetables[i]
+ if s.used then
+ local offset = s.subtables
+ setposition(f,cblctableoffset+offset)
+ for j=1,s.nofsubtables do
+ local firstindex = readushort(f)
+ local lastindex = readushort(f)
+ local tableoffset = readulong(f) + offset
+ for k=firstindex,lastindex do
+ if shapes[k] == i then
+ local s = subtables[tableoffset]
+ if not s then
+ s = {
+ firstindex = firstindex,
+ lastindex = lastindex,
+ }
+ subtables[tableoffset] = s
+ end
+ shapes[k] = s
end
end
end
- glyphoffset = nextoffset
end
end
- fontdata.sbixshapes = shapes
- -- else
- -- for i=1,nofstrikes do
- -- local strikeoffset = strikes[i] + tableoffset
- -- setposition(f,strikeoffset)
- -- local glyphs = { }
- -- strikes[i] = {
- -- ppem = readushort(f),
- -- ppi = readushort(f),
- -- glyphs = glyphs,
- -- }
- -- for i=0,nofglyphs do
- -- glyphs[i] = readulong(f)
- -- end
- -- local glyphoffset = glyphs[0]
- -- for i=0,nofglyphs-1 do
- -- local nextoffset = glyphs[i+1]
- -- local datasize = nextoffset - glyphoffset
- -- if datasize > 0 then
- -- setposition(f,strikeoffset + glyphoffset)
- -- glyphs[i] = {
- -- x = readshort(f),
- -- y = readshort(f),
- -- tag = readtag(f),
- -- data = readstring(f,datasize-8)
- -- }
- -- glyphoffset = nextoffset
- -- end
- -- end
- -- end
- -- fontdata.sbixshapes = strikes
+
+ -- there is no need to sort in string stream but we have a nicer trace
+ -- if needed
+
+ for offset, subtable in sortedhash(subtables) do
+ local tabletype = readushort(f)
+ subtable.format = readushort(f)
+ local baseoffset = readulong(f) + ctdttableoffset
+ local offsets = { }
+ local metrics = nil
+ if tabletype == 1 then
+ -- we have the usual one more to get the size
+ for i=subtable.firstindex,subtable.lastindex do
+ offsets[i] = readulong(f) + baseoffset
+ end
+ skipbytes(f,4)
+ elseif tabletype == 2 then
+ local size = readulong(f)
+ local done = baseoffset
+ metrics = getbigmetrics(f)
+ for i=subtable.firstindex,subtable.lastindex do
+ offsets[i] = done
+ done = done + size
+ end
+ elseif tabletype == 3 then
+ -- we have the usual one more to get the size
+ local n = subtable.lastindex - subtable.firstindex + 2
+ for i=subtable.firstindex,subtable.lastindex do
+ offsets[i] = readushort(f) + baseoffset
+ end
+ if math.odd(n) then
+ skipbytes(f,4)
+ else
+ skipbytes(f,2)
+ end
+ elseif tabletype == 4 then
+ for i=1,readulong(f) do
+ offsets[readushort(f)] = readushort(f) + baseoffset
+ end
+ elseif tabletype == 5 then
+ local size = readulong(f)
+ local done = baseoffset
+ metrics = getbigmetrics(f)
+ local n = readulong(f)
+ for i=1,n do
+ offsets[readushort(f)] = done
+ done = done + size
+ end
+ if math.odd(n) then
+ skipbytes(f,2)
+ end
+ else
+ return -- unsupported format
+ end
+ subtable.offsets = offsets
+ subtable.metrics = metrics
+ end
+
+ -- we only support a few sensible types ... there are hardly any fonts so
+ -- why are there so many variants ... not the best spec
+
+ local default = { width = 0, height = 0 }
+ local glyphs = fontdata.glyphs
+
+ for index, subtable in sortedhash(shapes) do
+ if type(subtable) == "table" then
+ local data = nil
+ local metrics = default
+ local format = subtable.format
+ local offset = subtable.offsets[index]
+ setposition(f,offset)
+ if format == 17 then
+ metrics = getsmallmetrics(f)
+ data = readstring(f,readulong(f))
+ elseif format == 18 then
+ metrics = getbigmetrics(f)
+ data = readstring(f,readulong(f))
+ elseif format == 19 then
+ metrics = subtable.metrics
+ data = readstring(f,readulong(f))
+ else
+ -- forget about it
+ end
+ local x = metrics.width
+ local y = metrics.height
+ shapes[index] = {
+ -- maybe some metrics
+ x = x,
+ y = y,
+ data = data,
+ }
+ -- I'll look into this in more details when needed
+ -- as we can use the bearings to get better boxes.
+ local glyph = glyphs[index]
+ if not glyph.boundingbox then
+ local width = glyph.width
+ local height = width * y/x
+ glyph.boundingbox = { 0, 0, width, height }
+ end
+
+ else
+ shapes[index] = {
+ x = 0,
+ y = 0,
+ data = "",
+ }
+ end
+ end
+
+ fontdata.pngshapes = shapes -- we cheat
+ end
+ end
+
+ function readers.cbdt(f,fontdata,specification)
+ -- local tableoffset = gotodatatable(f,fontdata,"ctdt",specification.glyphs)
+ -- if tableoffset then
+ -- local majorversion = readushort(f)
+ -- local minorversion = readushort(f)
-- end
end
-end
--- function readers.cblc(f,fontdata,specification)
--- local tableoffset = gotodatatable(f,fontdata,"cblc",specification.glyphs)
--- if tableoffset then
--- end
--- end
---
--- function readers.cbdt(f,fontdata,specification)
--- local tableoffset = gotodatatable(f,fontdata,"ctdt",specification.glyphs)
--- if tableoffset then
---
--- local function getmetrics(f)
--- return {
--- ascender = readinteger(f),
--- descender = readinteger(f),
--- widthmax = readcardinal(f),
--- caretslopedumerator = readinteger(f),
--- caretslopedenominator = readinteger(f),
--- caretoffset = readinteger(f),
--- minorigin = readinteger(f),
--- minadvance = readinteger(f),
--- maxbefore = readinteger(f),
--- minafter = readinteger(f),
--- pad1 = readinteger(f),
--- pad2 = readinteger(f),
--- }
--- end
---
--- local majorversion = readushort(f)
--- local minorversion = readushort(f)
--- local nofsizetables = readulong(f)
--- local sizetable = { }
--- for i=1,nofsizetables do
--- sizetable[i] = {
--- subtables = readulong(f),
--- indexsize = readulong(f),
--- nofsubtables = readulong(f),
--- colorref = readulong(f),
--- hormetrics = getmetrics(f),
--- vermetrics = getmetrics(f),
--- firstindex = readushort(f),
--- lastindex = readushort(f),
--- ppemx = readbyte(f),
--- ppemy = readbyte(f),
--- bitdepth = readbyte(f),
--- flags = readbyte(f),
--- }
--- end
---
--- sort(sizetable,function(a,b)
--- if b.ppemx == a.ppemx then
--- return b.bitdepth < a.bitdepth
--- else
--- return b.ppemx < a.ppemx
--- end
--- end)
---
--- local shapes = { }
---
--- for i=1,nofsizetables do
--- local s = sizetables[i]
--- for j=firstindex,lastindex do
--- if not shapes[j] then
--- shapes[j] = {
--- i
--- }
--- end
--- end
--- end
---
--- inspect(shapes)
---
--- end
--- end
+ -- function readers.ebdt(f,fontdata,specification)
+ -- if specification.glyphs then
+ -- end
+ -- end
--- function readers.ebdt(f,fontdata,specification)
--- if specification.glyphs then
--- end
--- end
+ -- function readers.ebsc(f,fontdata,specification)
+ -- if specification.glyphs then
+ -- end
+ -- end
--- function readers.ebsc(f,fontdata,specification)
--- if specification.glyphs then
--- end
--- end
+ -- function readers.eblc(f,fontdata,specification)
+ -- if specification.glyphs then
+ -- end
+ -- end
--- function readers.eblc(f,fontdata,specification)
--- if specification.glyphs then
--- end
--- end
+end
-- + AVAR : optional
-- + CFF2 : otf outlines
@@ -3398,7 +3502,8 @@ function readers.avar(f,fontdata,specification)
local lastfrom = false
local lastto = false
for i=1,nofvalues do
- local f, t = read2dot14(f), read2dot14(f)
+ local f = read2dot14(f)
+ local t = read2dot14(f)
if lastfrom and f <= lastfrom then
-- ignore
elseif lastto and t >= lastto then
@@ -3426,11 +3531,10 @@ function readers.avar(f,fontdata,specification)
return false
end
- local majorversion = readushort(f) -- 1
- local minorversion = readushort(f) -- 0
- local reserved = readushort(f)
- local nofaxis = readushort(f)
- local segments = { }
+ local version = readulong(f) -- 0x00010000
+ local reserved = readushort(f)
+ local nofaxis = readushort(f)
+ local segments = { }
for i=1,nofaxis do
segments[i] = collect()
end
@@ -3441,7 +3545,7 @@ end
function readers.fvar(f,fontdata,specification)
local tableoffset = gotodatatable(f,fontdata,"fvar",true) -- specification.variable or specification.instancenames
if tableoffset then
- local version = readulong(f) -- 1.0
+ local version = readulong(f) -- 0x00010000
local offsettoaxis = tableoffset + readushort(f)
local reserved = skipshort(f)
-- pair 1
@@ -3527,7 +3631,7 @@ function readers.hvar(f,fontdata,specification)
return
end
- local version = readulong(f) -- 1.0
+ local version = readulong(f) -- 0x00010000
local variationoffset = tableoffset + readulong(f) -- the store
local advanceoffset = tableoffset + readulong(f)
local lsboffset = tableoffset + readulong(f)
@@ -3624,7 +3728,7 @@ end
function readers.mvar(f,fontdata,specification)
local tableoffset = gotodatatable(f,fontdata,"mvar",specification.variable)
if tableoffset then
- local version = readulong(f) -- 1.0
+ local version = readulong(f) -- 0x00010000
local reserved = skipshort(f,1)
local recordsize = readushort(f)
local nofrecords = readushort(f)
diff --git a/tex/context/base/mkiv/font-emp.mkvi b/tex/context/base/mkiv/font-emp.mkvi
index 1b6d46798..b5c09d4c2 100644
--- a/tex/context/base/mkiv/font-emp.mkvi
+++ b/tex/context/base/mkiv/font-emp.mkvi
@@ -227,12 +227,22 @@
%D their style as good as possible. These macros are obsolete
%D in \MKIV.
-\unexpanded\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}}
-\unexpanded\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}}
-\unexpanded\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}}
-\unexpanded\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}}
-
-\unexpanded\def\emph {\groupedcommand{\em}{}}
+% \unexpanded\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}}
+% \unexpanded\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}}
+% \unexpanded\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}}
+% \unexpanded\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}}
+% \unexpanded\def\emph {\groupedcommand{\em}{}}
+
+\unexpanded\def\font_emphasis_bf{\bf\def\emphit{\bi}\def\emphsl{\bs}}
+\unexpanded\def\font_emphasis_it{\it\def\emphbf{\bi}\def\emphsl{\sl}}
+\unexpanded\def\font_emphasis_sl{\sl\def\emphbf{\bs}\def\emphit{\it}}
+\unexpanded\def\font_emphasis_tf{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}
+
+\unexpanded\def\emphbf{\triggergroupedcommandcs\font_emphasis_bf}
+\unexpanded\def\emphit{\triggergroupedcommandcs\font_emphasis_it}
+\unexpanded\def\emphsl{\triggergroupedcommandcs\font_emphasis_sl}
+\unexpanded\def\emphtf{\triggergroupedcommandcs\font_emphasis_tf}
+\unexpanded\def\emph {\triggergroupedcommandcs\em}
\unexpanded\def\emphasized{\bgroup\em\let\nexttoken}
diff --git a/tex/context/base/mkiv/font-enh.lua b/tex/context/base/mkiv/font-enh.lua
index b1fcd9be8..9ec116d47 100644
--- a/tex/context/base/mkiv/font-enh.lua
+++ b/tex/context/base/mkiv/font-enh.lua
@@ -115,7 +115,7 @@ local registerotffeature = otffeatures.register
----- tosixteen = fonts.mappings.tounicode16
-local function initializeunicoding(tfmdata)
+local function initialize(tfmdata)
local goodies = tfmdata.goodies
local newcoding = nil
for i=1,#goodies do
@@ -165,18 +165,14 @@ local function initializeunicoding(tfmdata)
end
end
-local unicoding_specification = {
+local specification = {
name = "unicoding",
description = "adapt unicode table",
initializers = {
- base = initializeunicoding,
- node = initializeunicoding,
+ base = initialize,
+ node = initialize,
},
- -- manipulators = {
- -- base = finalizeunicoding,
- -- node = finalizeunicoding,
- -- }
}
-registerotffeature(unicoding_specification)
-registerafmfeature(unicoding_specification)
+registerotffeature(specification)
+registerafmfeature(specification)
diff --git a/tex/context/base/mkiv/font-ext.lua b/tex/context/base/mkiv/font-ext.lua
deleted file mode 100644
index d873dccd4..000000000
--- a/tex/context/base/mkiv/font-ext.lua
+++ /dev/null
@@ -1,1856 +0,0 @@
-if not modules then modules = { } end modules ['font-ext'] = {
- version = 1.001,
- comment = "companion to font-ini.mkiv and hand-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local next, type, tonumber = next, type, tonumber
-local byte, find, formatters = string.byte, string.find, string.formatters
-local utfchar = utf.char
-local sortedhash, sortedkeys, sort = table.sortedhash, table.sortedkeys, table.sort
-
-local context = context
-local fonts = fonts
-local utilities = 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)
-
-local report_expansions = logs.reporter("fonts","expansions")
-local report_protrusions = logs.reporter("fonts","protrusions")
-
---[[ldx--
-<p>When we implement functions that deal with features, most of them
-will depend of the font format. Here we define the few that are kind
-of neutral.</p>
---ldx]]--
-
-local handlers = fonts.handlers
-local hashes = fonts.hashes
-local otf = handlers.otf
-local afm = handlers.afm
-
-local registerotffeature = otf.features.register
-local registerafmfeature = afm.features.register
-
-local fontdata = hashes.identifiers
-local fontproperties = hashes.properties
-
-local constructors = fonts.constructors
-local getprivate = constructors.getprivate
-
-local allocate = utilities.storage.allocate
-local settings_to_array = utilities.parsers.settings_to_array
-local settings_to_hash = utilities.parsers.settings_to_hash
-local getparameters = utilities.parsers.getparameters
-local gettexdimen = tex.getdimen
-local family_font = node.family_font
-
-local setmetatableindex = table.setmetatableindex
-
-local implement = interfaces.implement
-local variables = interfaces.variables
-
-
-local v_background = variables.background
-local v_frame = variables.frame
-local v_empty = variables.empty
-local v_none = variables.none
-
--- -- -- -- -- --
--- shared
--- -- -- -- -- --
-
-local function get_class_and_vector(tfmdata,value,where) -- "expansions"
- local g_where = tfmdata.goodies and tfmdata.goodies[where]
- local f_where = fonts[where]
- local g_classes = g_where and g_where.classes
- local f_classes = f_where and f_where.classes
- local class = (g_classes and g_classes[value]) or (f_classes and f_classes[value])
- if class then
- local class_vector = class.vector
- local g_vectors = g_where and g_where.vectors
- local f_vectors = f_where and f_where.vectors
- local vector = (g_vectors and g_vectors[class_vector]) or (f_vectors and f_vectors[class_vector])
- return class, vector
- end
-end
-
--- -- -- -- -- --
--- expansion (hz)
--- -- -- -- -- --
-
-local expansions = fonts.expansions or allocate()
-
-fonts.expansions = expansions
-
-local classes = expansions.classes or allocate()
-local vectors = expansions.vectors or allocate()
-
-expansions.classes = classes
-expansions.vectors = vectors
-
--- beware, pdftex itself uses percentages * 10
---
--- todo: get rid of byte() here
-
-classes.preset = { stretch = 2, shrink = 2, step = .5, factor = 1 }
-
-classes['quality'] = {
- stretch = 2, shrink = 2, step = .5, vector = 'default', factor = 1
-}
-
-vectors['default'] = {
- [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7,
- [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7,
- [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7,
- [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7,
- [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7,
- [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7,
- [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7,
- [byte('w')] = 0.7, [byte('z')] = 0.7,
- [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7,
-}
-
-vectors['quality'] = vectors['default'] -- metatable ?
-
-local function initializeexpansion(tfmdata,value)
- if value then
- local class, vector = get_class_and_vector(tfmdata,value,"expansions")
- if class then
- if vector then
- local stretch = class.stretch or 0
- local shrink = class.shrink or 0
- local step = class.step or 0
- local factor = class.factor or 1
- if trace_expansion then
- report_expansions("setting class %a, vector %a, factor %a, stretch %a, shrink %a, step %a",
- value,class.vector,factor,stretch,shrink,step)
- end
- tfmdata.parameters.expansion = {
- stretch = 10 * stretch,
- shrink = 10 * shrink,
- step = 10 * step,
- factor = factor,
- }
- local data = characters and characters.data
- for i, chr in next, tfmdata.characters do
- local v = vector[i]
- if data and not v then -- we could move the data test outside (needed for plain)
- local d = data[i]
- if d then
- local s = d.shcode
- if not s then
- -- sorry
- elseif type(s) == "table" then
- v = ((vector[s[1]] or 0) + (vector[s[#s]] or 0)) / 2
- else
- v = vector[s] or 0
- end
- end
- end
- if v and v ~= 0 then
- chr.expansion_factor = v*factor
- else -- can be option
- chr.expansion_factor = factor
- end
- end
- elseif trace_expansion then
- report_expansions("unknown vector %a in class %a",class.vector,value)
- end
- elseif trace_expansion then
- report_expansions("unknown class %a",value)
- end
- end
-end
-
-local expansion_specification = {
- name = "expansion",
- description = "apply hz optimization",
- initializers = {
- base = initializeexpansion,
- node = initializeexpansion,
- }
-}
-
-registerotffeature(expansion_specification)
-registerafmfeature(expansion_specification)
-
-fonts.goodies.register("expansions", function(...) return fonts.goodies.report("expansions", trace_expansion, ...) end)
-
-implement {
- name = "setupfontexpansion",
- arguments = "2 strings",
- actions = function(class,settings) getparameters(classes,class,'preset',settings) end
-}
-
--- -- -- -- -- --
--- protrusion
--- -- -- -- -- --
-
-fonts.protrusions = allocate()
-local protrusions = fonts.protrusions
-
-protrusions.classes = allocate()
-protrusions.vectors = allocate()
-
-local classes = protrusions.classes
-local vectors = protrusions.vectors
-
--- the values need to be revisioned
-
-classes.preset = { factor = 1, left = 1, right = 1 }
-
-classes['pure'] = {
- vector = 'pure', factor = 1
-}
-classes['punctuation'] = {
- vector = 'punctuation', factor = 1
-}
-classes['alpha'] = {
- vector = 'alpha', factor = 1
-}
-classes['quality'] = {
- vector = 'quality', factor = 1
-}
-
-vectors['pure'] = {
-
- [0x002C] = { 0, 1 }, -- comma
- [0x002E] = { 0, 1 }, -- period
- [0x003A] = { 0, 1 }, -- colon
- [0x003B] = { 0, 1 }, -- semicolon
- [0x002D] = { 0, 1 }, -- hyphen
- [0x00AD] = { 0, 1 }, -- also hyphen
- [0x2013] = { 0, 0.50 }, -- endash
- [0x2014] = { 0, 0.33 }, -- emdash
- [0x3001] = { 0, 1 }, -- ideographic comma 、
- [0x3002] = { 0, 1 }, -- ideographic full stop 。
- [0x060C] = { 0, 1 }, -- arabic comma ،
- [0x061B] = { 0, 1 }, -- arabic semicolon ؛
- [0x06D4] = { 0, 1 }, -- arabic full stop ۔
-
-}
-
-vectors['punctuation'] = {
-
- [0x003F] = { 0, 0.20 }, -- ?
- [0x00BF] = { 0, 0.20 }, -- ¿
- [0x0021] = { 0, 0.20 }, -- !
- [0x00A1] = { 0, 0.20 }, -- ¡
- [0x0028] = { 0.05, 0 }, -- (
- [0x0029] = { 0, 0.05 }, -- )
- [0x005B] = { 0.05, 0 }, -- [
- [0x005D] = { 0, 0.05 }, -- ]
- [0x002C] = { 0, 0.70 }, -- comma
- [0x002E] = { 0, 0.70 }, -- period
- [0x003A] = { 0, 0.50 }, -- colon
- [0x003B] = { 0, 0.50 }, -- semicolon
- [0x002D] = { 0, 0.70 }, -- hyphen
- [0x00AD] = { 0, 0.70 }, -- also hyphen
- [0x2013] = { 0, 0.30 }, -- endash
- [0x2014] = { 0, 0.20 }, -- emdash
- [0x060C] = { 0, 0.70 }, -- arabic comma
- [0x061B] = { 0, 0.50 }, -- arabic semicolon
- [0x06D4] = { 0, 0.70 }, -- arabic full stop
- [0x061F] = { 0, 0.20 }, -- ؟
-
- -- todo: left and right quotes: .5 double, .7 single
-
- [0x2039] = { 0.70, 0.70 }, -- left single guillemet ‹
- [0x203A] = { 0.70, 0.70 }, -- right single guillemet ›
- [0x00AB] = { 0.50, 0.50 }, -- left guillemet «
- [0x00BB] = { 0.50, 0.50 }, -- right guillemet »
-
- [0x2018] = { 0.70, 0.70 }, -- left single quotation mark ‘
- [0x2019] = { 0, 0.70 }, -- right single quotation mark ’
- [0x201A] = { 0.70, 0 }, -- single low-9 quotation mark ,
- [0x201B] = { 0.70, 0 }, -- single high-reversed-9 quotation mark ‛
- [0x201C] = { 0.50, 0.50 }, -- left double quotation mark “
- [0x201D] = { 0, 0.50 }, -- right double quotation mark ”
- [0x201E] = { 0.50, 0 }, -- double low-9 quotation mark „
- [0x201F] = { 0.50, 0 }, -- double high-reversed-9 quotation mark ‟
-
-}
-
-vectors['alpha'] = {
-
- [byte("A")] = { .05, .05 },
- [byte("F")] = { 0, .05 },
- [byte("J")] = { .05, 0 },
- [byte("K")] = { 0, .05 },
- [byte("L")] = { 0, .05 },
- [byte("T")] = { .05, .05 },
- [byte("V")] = { .05, .05 },
- [byte("W")] = { .05, .05 },
- [byte("X")] = { .05, .05 },
- [byte("Y")] = { .05, .05 },
-
- [byte("k")] = { 0, .05 },
- [byte("r")] = { 0, .05 },
- [byte("t")] = { 0, .05 },
- [byte("v")] = { .05, .05 },
- [byte("w")] = { .05, .05 },
- [byte("x")] = { .05, .05 },
- [byte("y")] = { .05, .05 },
-
-}
-
-vectors['quality'] = table.merged(
- vectors['punctuation'],
- vectors['alpha']
-)
-
--- As this is experimental code, users should not depend on it. The implications are still
--- discussed on the ConTeXt Dev List and we're not sure yet what exactly the spec is (the
--- next code is tested with a gyre font patched by / fea file made by Khaled Hosny). The
--- double trick should not be needed it proper hanging punctuation is used in which case
--- values < 1 can be used.
---
--- preferred (in context, usine vectors):
---
--- \definefontfeature[whatever][default][mode=node,protrusion=quality]
---
--- using lfbd and rtbd, with possibibility to enable only one side :
---
--- \definefontfeature[whocares][default][mode=node,protrusion=yes, opbd=yes,script=latn]
--- \definefontfeature[whocares][default][mode=node,protrusion=right,opbd=yes,script=latn]
---
--- idem, using multiplier
---
--- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn]
--- \definefontfeature[whocares][default][mode=node,protrusion=double,opbd=yes,script=latn]
---
--- idem, using named feature file (less frozen):
---
--- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea]
-
-classes['double'] = { -- for testing opbd
- factor = 2, left = 1, right = 1,
-}
-
-local function map_opbd_onto_protrusion(tfmdata,value,opbd)
- local characters = tfmdata.characters
- local descriptions = tfmdata.descriptions
- local properties = tfmdata.properties
- local resources = tfmdata.resources
- local rawdata = tfmdata.shared.rawdata
- local lookuphash = rawdata.lookuphash
- local lookuptags = resources.lookuptags
- local script = properties.script
- local language = properties.language
- local done, factor, left, right = false, 1, 1, 1
- local class = classes[value]
- if class then
- factor = class.factor or 1
- left = class.left or 1
- right = class.right or 1
- else
- factor = tonumber(value) or 1
- end
- if opbd ~= "right" then
- local validlookups, lookuplist = otf.collectlookups(rawdata,"lfbd",script,language)
- if validlookups then
- for i=1,#lookuplist do
- local lookup = lookuplist[i]
- local steps = lookup.steps
- if steps then
- if trace_protrusion then
- report_protrusions("setting left using lfbd")
- end
- for i=1,#steps do
- local step = steps[i]
- local coverage = step.coverage
- if coverage then
- for k, v in next, coverage do
- -- local p = - v[3] / descriptions[k].width-- or 1 ~= 0 too but the same
- local p = - (v[1] / 1000) * factor * left
- characters[k].left_protruding = p
- if trace_protrusion then
- report_protrusions("lfbd -> %C -> %p",k,p)
- end
- end
- end
- end
- done = true
- end
- end
- end
- end
- if opbd ~= "left" then
- local validlookups, lookuplist = otf.collectlookups(rawdata,"rtbd",script,language)
- if validlookups then
- for i=1,#lookuplist do
- local lookup = lookuplist[i]
- local steps = lookup.steps
- if steps then
- if trace_protrusion then
- report_protrusions("setting right using rtbd")
- end
- for i=1,#steps do
- local step = steps[i]
- local coverage = step.coverage
- if coverage then
- for k, v in next, coverage do
- -- local p = v[3] / descriptions[k].width -- or 3
- local p = (v[1] / 1000) * factor * right
- characters[k].right_protruding = p
- if trace_protrusion then
- report_protrusions("rtbd -> %C -> %p",k,p)
- end
- end
- end
- end
- end
- done = true
- end
- end
- end
-end
-
--- The opbd test is just there because it was discussed on the context development list. However,
--- the mentioned fxlbi.otf font only has some kerns for digits. So, consider this feature not supported
--- till we have a proper test font.
-
-local function initializeprotrusion(tfmdata,value)
- if value then
- local opbd = tfmdata.shared.features.opbd
- if opbd then
- -- possible values: left right both yes no (experimental)
- map_opbd_onto_protrusion(tfmdata,value,opbd)
- else
- local class, vector = get_class_and_vector(tfmdata,value,"protrusions")
- if class then
- if vector then
- local factor = class.factor or 1
- local left = class.left or 1
- local right = class.right or 1
- if trace_protrusion then
- report_protrusions("setting class %a, vector %a, factor %a, left %a, right %a",
- value,class.vector,factor,left,right)
- end
- local data = characters.data
- local emwidth = tfmdata.parameters.quad
- tfmdata.parameters.protrusion = {
- factor = factor,
- left = left,
- right = right,
- }
- for i, chr in next, tfmdata.characters do
- local v, pl, pr = vector[i], nil, nil
- if v then
- pl, pr = v[1], v[2]
- else
- local d = data[i]
- if d then
- local s = d.shcode
- if not s then
- -- sorry
- elseif type(s) == "table" then
- local vl, vr = vector[s[1]], vector[s[#s]]
- if vl then pl = vl[1] end
- if vr then pr = vr[2] end
- else
- v = vector[s]
- if v then
- pl, pr = v[1], v[2]
- end
- end
- end
- end
- if pl and pl ~= 0 then
- chr.left_protruding = left *pl*factor
- end
- if pr and pr ~= 0 then
- chr.right_protruding = right*pr*factor
- end
- end
- elseif trace_protrusion then
- report_protrusions("unknown vector %a in class %a",class.vector,value)
- end
- elseif trace_protrusion then
- report_protrusions("unknown class %a",value)
- end
- end
- end
-end
-
-local protrusion_specification = {
- name = "protrusion",
- description = "l/r margin character protrusion",
- initializers = {
- base = initializeprotrusion,
- node = initializeprotrusion,
- }
-}
-
-registerotffeature(protrusion_specification)
-registerafmfeature(protrusion_specification)
-
-fonts.goodies.register("protrusions", function(...) return fonts.goodies.report("protrusions", trace_protrusion, ...) end)
-
-implement {
- name = "setupfontprotrusion",
- arguments = "2 strings",
- actions = function(class,settings) getparameters(classes,class,'preset',settings) end
-}
-
--- -- --
-
-local function initializenostackmath(tfmdata,value)
- tfmdata.properties.nostackmath = value and true
-end
-
-registerotffeature {
- name = "nostackmath",
- description = "disable math stacking mechanism",
- initializers = {
- base = initializenostackmath,
- node = initializenostackmath,
- }
-}
-
-local function initializerealdimensions(tfmdata,value)
- tfmdata.properties.realdimensions = value and true
-end
-
-registerotffeature {
- name = "realdimensions",
- description = "accept negative dimenions",
- initializers = {
- base = initializerealdimensions,
- node = initializerealdimensions,
- }
-}
-
-local function initializeitlc(tfmdata,value) -- hm, always value
- if value then
- -- 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 properties = tfmdata.properties
- local factor = tonumber(value) or 1
- properties.hasitalics = true
- properties.autoitalicamount = factor * (parameters.uwidth or 40)/2
- end
- end
-end
-
-local italic_specification = {
- name = "itlc",
- description = "italic correction",
- initializers = {
- base = initializeitlc,
- node = initializeitlc,
- }
-}
-
-registerotffeature(italic_specification)
-registerafmfeature(italic_specification)
-
-local function initializetextitalics(tfmdata,value) -- yes no delay
- tfmdata.properties.textitalics = toboolean(value)
-end
-
-local textitalics_specification = {
- name = "textitalics",
- description = "use alternative text italic correction",
- initializers = {
- base = initializetextitalics,
- node = initializetextitalics,
- }
-}
-
-registerotffeature(textitalics_specification)
-registerafmfeature(textitalics_specification)
-
--- local function initializemathitalics(tfmdata,value) -- yes no delay
--- tfmdata.properties.mathitalics = toboolean(value)
--- end
---
--- local mathitalics_specification = {
--- name = "mathitalics",
--- description = "use alternative math italic correction",
--- initializers = {
--- base = initializemathitalics,
--- node = initializemathitalics,
--- }
--- }
-
--- registerotffeature(mathitalics_specification)
--- registerafmfeature(mathitalics_specification)
-
--- slanting
-
-local function initializeslant(tfmdata,value)
- value = tonumber(value)
- if not value then
- value = 0
- elseif value > 1 then
- value = 1
- elseif value < -1 then
- value = -1
- end
- tfmdata.parameters.slantfactor = value
-end
-
-local slant_specification = {
- name = "slant",
- description = "slant glyphs",
- initializers = {
- base = initializeslant,
- node = initializeslant,
- }
-}
-
-registerotffeature(slant_specification)
-registerafmfeature(slant_specification)
-
-local function initializeextend(tfmdata,value)
- value = tonumber(value)
- if not value then
- value = 0
- elseif value > 10 then
- value = 10
- elseif value < -10 then
- value = -10
- end
- tfmdata.parameters.extendfactor = value
-end
-
-local extend_specification = {
- name = "extend",
- description = "scale glyphs horizontally",
- initializers = {
- base = initializeextend,
- node = initializeextend,
- }
-}
-
-registerotffeature(extend_specification)
-registerafmfeature(extend_specification)
-
--- For Wolfgang Schuster:
---
--- \definefontfeature[thisway][default][script=hang,language=zhs,dimensions={2,2,2}]
--- \definedfont[file:kozminpr6nregular*thisway]
---
--- For the moment we don't mess with the descriptions.
-
-local function manipulatedimensions(tfmdata,key,value)
- if type(value) == "string" and value ~= "" then
- local characters = tfmdata.characters
- local parameters = tfmdata.parameters
- local emwidth = parameters.quad
- local exheight = parameters.xheight
- local newwidth = false
- local newheight = false
- local newdepth = false
- if value == "strut" then
- newheight = gettexdimen("strutht")
- newdepth = gettexdimen("strutdp")
- elseif value == "mono" then
- newwidth = emwidth
- else
- local spec = settings_to_array(value)
- newwidth = tonumber(spec[1])
- newheight = tonumber(spec[2])
- newdepth = tonumber(spec[3])
- if newwidth then newwidth = newwidth * emwidth end
- if newheight then newheight = newheight * exheight end
- if newdepth then newdepth = newdepth * exheight end
- end
- if newwidth or newheight or newdepth then
- local additions = { }
- for unicode, old_c in next, characters do
- local oldwidth = old_c.width
- local oldheight = old_c.height
- local olddepth = old_c.depth
- local width = newwidth or oldwidth or 0
- local height = newheight or oldheight or 0
- local depth = newdepth or olddepth or 0
- if oldwidth ~= width or oldheight ~= height or olddepth ~= depth then
- local private = getprivate(tfmdata)
- local newslot = { "slot", 1, private } -- { "slot", 0, private }
- local new_c
- local commands = oldwidth ~= width and {
- { "right", (width - oldwidth) / 2 },
- newslot,
- } or {
- newslot,
- }
- if height > 0 then
- if depth > 0 then
- new_c = {
- width = width,
- height = height,
- depth = depth,
- commands = commands,
- }
- else
- new_c = {
- width = width,
- height = height,
- commands = commands,
- }
- end
- else
- if depth > 0 then
- new_c = {
- width = width,
- depth = depth,
- commands = commands,
- }
- else
- new_c = {
- width = width,
- commands = commands,
- }
- end
- end
- setmetatableindex(new_c,old_c)
- characters[unicode] = new_c
- additions[private] = old_c
- end
- end
- for k, v in next, additions do
- characters[k] = v
- end
- -- elseif height > 0 and depth > 0 then
- -- for unicode, old_c in next, characters do
- -- old_c.height = height
- -- old_c.depth = depth
- -- end
- -- elseif height > 0 then
- -- for unicode, old_c in next, characters do
- -- old_c.height = height
- -- end
- -- elseif depth > 0 then
- -- for unicode, old_c in next, characters do
- -- old_c.depth = depth
- -- end
- end
- end
-end
-
-local dimensions_specification = {
- name = "dimensions",
- description = "force dimensions",
- manipulators = {
- base = manipulatedimensions,
- node = manipulatedimensions,
- }
-}
-
-registerotffeature(dimensions_specification)
-registerafmfeature(dimensions_specification)
-
---------------------------------------------------------------------------------------------------------------
-
--- local function fakemonospace(tfmdata)
--- local resources = tfmdata.resources
--- local gposfeatures = resources.features.gpos
--- local characters = tfmdata.characters
--- local descriptions = tfmdata.descriptions
--- local sequences = resources.sequences
--- local coverage = { }
--- local units = tfmdata.shared.rawdata.metadata.units
--- for k, v in next, characters do
--- local w = descriptions[k].width
--- local d = units - w
--- coverage[k] = { -d/2, 0, units, 0 }
--- end
--- local f = { dflt = { dflt = true } }
--- local s = #sequences + 1
--- local t = {
--- features = { fakemono = f },
--- flags = { false, false, false, false },
--- index = s,
--- name = "p_s_" .. s,
--- nofsteps = 1,
--- order = { "fakemono" },
--- skiphash = false,
--- type = "gpos_single",
--- steps = {
--- {
--- format = "single",
--- coverage = coverage,
--- }
--- }
--- }
--- gposfeatures["fakemono"] = f
--- sequences[s] = t
--- end
---
--- fonts.constructors.features.otf.register {
--- name = "fakemono",
--- description = "fake monospaced",
--- initializers = {
--- node = fakemonospace,
--- },
--- }
-
---------------------------------------------------------------------------------------------------------------
-
--- for zhichu chen (see mailing list archive): we might add a few more variants
--- in due time
---
--- \definefontfeature[boxed][default][boundingbox=yes] % paleblue
---
--- maybe:
---
--- \definecolor[DummyColor][s=.75,t=.5,a=1] {\DummyColor test} \nopdfcompression
---
--- local gray = { "pdf", "origin", "/Tr1 gs .75 g" }
--- local black = { "pdf", "origin", "/Tr0 gs 0 g" }
-
-
--- boundingbox={yes|background|frame|empty|<color>}
-
-local push = { "push" }
-local pop = { "pop" }
-
------ gray = { "pdf", "origin", ".75 g .75 G" }
------ black = { "pdf", "origin", "0 g 0 G" }
------ gray = { "pdf", ".75 g" }
------ black = { "pdf", "0 g" }
-
--- local bp = number.dimenfactors.bp
---
--- local downcache = setmetatableindex(function(t,d)
--- local v = { "down", d }
--- t[d] = v
--- return v
--- end)
---
--- local backcache = setmetatableindex(function(t,h)
--- local h = h * bp
--- local v = setmetatableindex(function(t,w)
--- -- local v = { "rule", h, w }
--- local v = { "pdf", "origin", formatters["0 0 %.6F %.6F re F"](w*bp,h) }
--- t[w] = v
--- return v
--- end)
--- t[h] = v
--- return v
--- end)
---
--- local forecache = setmetatableindex(function(t,h)
--- local h = h * bp
--- local v = setmetatableindex(function(t,w)
--- local v = { "pdf", "origin", formatters["%.6F w 0 0 %.6F %.6F re S"](0.25*65536*bp,w*bp,h) }
--- t[w] = v
--- return v
--- end)
--- t[h] = v
--- return v
--- end)
-
-local bp = number.dimenfactors.bp
-local r = 16384 * bp -- 65536 // 4
-
-local backcache = setmetatableindex(function(t,h)
- local h = h * bp
- local v = setmetatableindex(function(t,d)
- local d = d * bp
- local v = setmetatableindex(function(t,w)
- local v = { "pdf", "origin", formatters["%.6F w 0 %.6F %.6F %.6F re f"](r,-d,w*bp,h+d) }
- t[w] = v
- return v
- end)
- t[d] = v
- return v
- end)
- t[h] = v
- return v
-end)
-
-local forecache = setmetatableindex(function(t,h)
- local h = h * bp
- local v = setmetatableindex(function(t,d)
- local d = d * bp
- local v = setmetatableindex(function(t,w)
- -- the frame goes through the boundingbox
- -- local v = { "pdf", "origin", formatters["[] 0 d 0 J %.6F w %.6F %.6F %.6F re S"](r,-d,w*bp,h+d) }
- local v = { "pdf", "origin", formatters["[] 0 d 0 J %.6F w %.6F %.6F %.6F %.6F re S"](r,r/2,-d+r/2,w*bp-r,h+d-r) }
- t[w] = v
- return v
- end)
- t[d] = v
- return v
- end)
- t[h] = v
- return v
-end)
-
-local startcolor = nil
-local stopcolor = nil
-
-local function showboundingbox(tfmdata,key,value)
- if value then
- if not backcolors then
- local vfspecials = backends.pdf.tables.vfspecials
- startcolor = vfspecials.startcolor
- stopcolor = vfspecials.stopcolor
- end
- local characters = tfmdata.characters
- local additions = { }
- local rulecache = backcache
- local showchar = true
- local color = "palegray"
- if type(value) == "string" then
- value = settings_to_array(value)
- for i=1,#value do
- local v = value[i]
- if v == v_frame then
- rulecache = forecache
- elseif v == v_background then
- rulecache = backcache
- elseif v == v_empty then
- showchar = false
- elseif v == v_none then
- color = nil
- else
- color = v
- end
- end
- end
- local gray = color and startcolor(color) or nil
- local black = gray and stopcolor or nil
- for unicode, old_c in next, characters do
- local private = getprivate(tfmdata)
- local width = old_c.width or 0
- local height = old_c.height or 0
- local depth = old_c.depth or 0
- local char = showchar and { "slot", 1, private } or nil -- { "slot", 0, private }
- -- local new_c
- -- if depth == 0 then
- -- new_c = {
- -- width = width,
- -- height = height,
- -- commands = {
- -- push,
- -- gray,
- -- rulecache[height][width],
- -- black,
- -- pop,
- -- char,
- -- }
- -- }
- -- else
- -- new_c = {
- -- width = width,
- -- height = height,
- -- depth = depth,
- -- commands = {
- -- push,
- -- downcache[depth],
- -- gray,
- -- rulecache[height+depth][width],
- -- black,
- -- pop,
- -- char,
- -- }
- -- }
- -- end
- local rule = rulecache[height][depth][width]
- local new_c = {
- width = width,
- height = height,
- depth = depth,
- commands = gray and {
- -- push,
- gray,
- rule,
- black,
- -- pop,
- char,
- } or {
- rule,
- char,
- }
- }
- setmetatableindex(new_c,old_c)
- characters[unicode] = new_c
- additions[private] = old_c
- end
- for k, v in next, additions do
- characters[k] = v
- end
- end
-end
-
-registerotffeature {
- name = "boundingbox",
- description = "show boundingbox",
- manipulators = {
- base = showboundingbox,
- node = showboundingbox,
- }
-}
-
--- -- for notosans but not general
---
--- do
---
--- local v_local = interfaces and interfaces.variables and interfaces.variables["local"] or "local"
---
--- local utfbyte = utf.byte
---
--- local function initialize(tfmdata,key,value)
--- local characters = tfmdata.characters
--- local parameters = tfmdata.parameters
--- local oldchar = 32
--- local newchar = 32
--- if value == "locl" or value == v_local then
--- newchar = fonts.handlers.otf.getsubstitution(tfmdata,oldchar,"locl",true) or oldchar
--- elseif value == true then
--- -- use normal space
--- elseif value then
--- newchar = utfbyte(value)
--- else
--- return
--- end
--- local newchar = newchar and characters[newchar]
--- local newspace = newchar and newchar.width
--- if newspace > 0 then
--- parameters.space = newspace
--- parameters.space_stretch = newspace/2
--- parameters.space_shrink = newspace/3
--- parameters.extra_space = parameters.space_shrink
--- end
--- end
---
--- registerotffeature {
--- name = 'space', -- true|false|locl|character
--- description = 'space settings',
--- manipulators = {
--- base = initialize,
--- node = initialize,
--- }
--- }
---
--- end
-
-do
-
- local P, lpegpatterns, lpegmatch = lpeg.P, lpeg.patterns, lpeg.match
-
- local amount, stretch, shrink, extra
-
- local factor = lpegpatterns.unsigned
- local space = lpegpatterns.space
- local pattern = (
- (factor / function(n) amount = tonumber(n) or amount end)
- + (P("+") + P("plus" )) * space^0 * (factor / function(n) stretch = tonumber(n) or stretch end)
- + (P("-") + P("minus")) * space^0 * (factor / function(n) shrink = tonumber(n) or shrink end)
- + ( P("extra")) * space^0 * (factor / function(n) extra = tonumber(n) or extra end)
- + space^1
- )^1
-
- local function initialize(tfmdata,key,value)
- local characters = tfmdata.characters
- local parameters = tfmdata.parameters
- if type(value) == "string" then
- local emwidth = parameters.quad
- amount, stretch, shrink, extra = 0, 0, 0, false
- lpegmatch(pattern,value)
- if not extra then
- if shrink ~= 0 then
- extra = shrink
- elseif stretch ~= 0 then
- extra = stretch
- else
- extra = amount
- end
- end
- parameters.space = amount * emwidth
- parameters.space_stretch = stretch * emwidth
- parameters.space_shrink = shrink * emwidth
- parameters.extra_space = extra * emwidth
- end
- end
-
- -- 1.1 + 1.2 - 1.3 minus 1.4 plus 1.1 extra 1.4 -- last one wins
-
- registerotffeature {
- name = "spacing",
- description = "space settings",
- manipulators = {
- base = initialize,
- node = initialize,
- }
- }
-
-end
-
--- -- historic stuff, move from font-ota (handled differently, typo-rep)
---
--- local delete_node = nodes.delete
--- local fontdata = fonts.hashes.identifiers
---
--- local nodecodes = nodes.nodecodes
--- local glyph_code = nodecodes.glyph
---
--- local strippables = allocate()
--- fonts.strippables = strippables
---
--- strippables.joiners = table.tohash {
--- 0x200C, -- zwnj
--- 0x200D, -- zwj
--- }
---
--- strippables.all = table.tohash {
--- 0x000AD, 0x017B4, 0x017B5, 0x0200B, 0x0200C, 0x0200D, 0x0200E, 0x0200F, 0x0202A, 0x0202B,
--- 0x0202C, 0x0202D, 0x0202E, 0x02060, 0x02061, 0x02062, 0x02063, 0x0206A, 0x0206B, 0x0206C,
--- 0x0206D, 0x0206E, 0x0206F, 0x0FEFF, 0x1D173, 0x1D174, 0x1D175, 0x1D176, 0x1D177, 0x1D178,
--- 0x1D179, 0x1D17A, 0xE0001, 0xE0020, 0xE0021, 0xE0022, 0xE0023, 0xE0024, 0xE0025, 0xE0026,
--- 0xE0027, 0xE0028, 0xE0029, 0xE002A, 0xE002B, 0xE002C, 0xE002D, 0xE002E, 0xE002F, 0xE0030,
--- 0xE0031, 0xE0032, 0xE0033, 0xE0034, 0xE0035, 0xE0036, 0xE0037, 0xE0038, 0xE0039, 0xE003A,
--- 0xE003B, 0xE003C, 0xE003D, 0xE003E, 0xE003F, 0xE0040, 0xE0041, 0xE0042, 0xE0043, 0xE0044,
--- 0xE0045, 0xE0046, 0xE0047, 0xE0048, 0xE0049, 0xE004A, 0xE004B, 0xE004C, 0xE004D, 0xE004E,
--- 0xE004F, 0xE0050, 0xE0051, 0xE0052, 0xE0053, 0xE0054, 0xE0055, 0xE0056, 0xE0057, 0xE0058,
--- 0xE0059, 0xE005A, 0xE005B, 0xE005C, 0xE005D, 0xE005E, 0xE005F, 0xE0060, 0xE0061, 0xE0062,
--- 0xE0063, 0xE0064, 0xE0065, 0xE0066, 0xE0067, 0xE0068, 0xE0069, 0xE006A, 0xE006B, 0xE006C,
--- 0xE006D, 0xE006E, 0xE006F, 0xE0070, 0xE0071, 0xE0072, 0xE0073, 0xE0074, 0xE0075, 0xE0076,
--- 0xE0077, 0xE0078, 0xE0079, 0xE007A, 0xE007B, 0xE007C, 0xE007D, 0xE007E, 0xE007F,
--- }
---
--- strippables[true] = strippables.joiners
---
--- local function processformatters(head,font)
--- local subset = fontdata[font].shared.features.formatters
--- local vector = subset and strippables[subset]
--- if vector then
--- local current, done = head, false
--- while current do
--- if current.id == glyph_code and current.subtype<256 and current.font == font then
--- local char = current.char
--- if vector[char] then
--- head, current = delete_node(head,current)
--- done = true
--- else
--- current = current.next
--- end
--- else
--- current = current.next
--- end
--- end
--- return head, done
--- else
--- return head, false
--- end
--- end
---
--- registerotffeature {
--- name = "formatters",
--- description = "hide formatting characters",
--- methods = {
--- base = processformatters,
--- node = processformatters,
--- }
--- }
-
--- not to be used! experimental code, only needed when testing
-
-local is_letter = characters.is_letter
-local always = true
-
-local function collapseitalics(tfmdata,key,value)
- local threshold = value == true and 100 or tonumber(value)
- if threshold and threshold > 0 then
- if threshold > 100 then
- threshold = 100
- end
- for unicode, data in next, tfmdata.characters do
- if always or is_letter[unicode] or is_letter[data.unicode] then
- local italic = data.italic
- if italic and italic ~= 0 then
- local width = data.width
- if width and width ~= 0 then
- local delta = threshold * italic / 100
- data.width = width + delta
- data.italic = italic - delta
- end
- end
- end
- end
- end
-end
-
-local dimensions_specification = {
- name = "collapseitalics",
- description = "collapse italics",
- manipulators = {
- base = collapseitalics,
- node = collapseitalics,
- }
-}
-
-registerotffeature(dimensions_specification)
-registerafmfeature(dimensions_specification)
-
--- a handy helper (might change or be moved to another namespace)
-
-local nodepool = nodes.pool
-local new_glyph = nodepool.glyph
-
-local helpers = fonts.helpers
-local currentfont = font.current
-
-local currentprivate = 0xE000
-local maximumprivate = 0xEFFF
-
--- if we run out of space we can think of another range but by sharing we can
--- use these privates for mechanisms like alignments-on-character and such
-
-local sharedprivates = setmetatableindex(function(t,k)
- v = currentprivate
- if currentprivate < maximumprivate then
- currentprivate = currentprivate + 1
- else
- -- reuse last slot, todo: warning
- end
- t[k] = v
- return v
-end)
-
-function helpers.addprivate(tfmdata,name,characterdata)
- local properties = tfmdata.properties
- local characters = tfmdata.characters
- local privates = properties.privates
- if not privates then
- privates = { }
- properties.privates = privates
- end
- if not name then
- name = formatters["anonymous_private_0x%05X"](currentprivate)
- end
- local usedprivate = sharedprivates[name]
- privates[name] = usedprivate
- characters[usedprivate] = characterdata
- return usedprivate
-end
-
-local function getprivateslot(id,name)
- if not name then
- name = id
- id = currentfont()
- end
- local properties = fontproperties[id]
- local privates = properties and properties.privates
- return privates and privates[name]
-end
-
-local function getprivatenode(tfmdata,name)
- if type(tfmdata) == "number" then
- tfmdata = fontdata[tfmdata]
- end
- local properties = tfmdata.properties
- local font = properties.id
- local slot = getprivateslot(font,name)
- if slot then
- -- todo: set current attribibutes
- local char = tfmdata.characters[slot]
- local tonode = char.tonode
- if tonode then
- return tonode(font,char)
- else
- return new_glyph(font,slot)
- end
- end
-end
-
-local function getprivatecharornode(tfmdata,name)
- if type(tfmdata) == "number" then
- tfmdata = fontdata[tfmdata]
- end
- local properties = tfmdata.properties
- local font = properties.id
- local slot = getprivateslot(font,name)
- if slot then
- -- todo: set current attributes
- local char = tfmdata.characters[slot]
- local tonode = char.tonode
- if tonode then
- return "node", tonode(tfmdata,char)
- else
- return "char", slot
- end
- end
-end
-
-helpers.getprivateslot = getprivateslot
-helpers.getprivatenode = getprivatenode
-helpers.getprivatecharornode = getprivatecharornode
-
-function helpers.getprivates(tfmdata)
- if type(tfmdata) == "number" then
- tfmdata = fontdata[tfmdata]
- end
- local properties = tfmdata.properties
- return properties and properties.privates
-end
-
-function helpers.hasprivate(tfmdata,name)
- if type(tfmdata) == "number" then
- tfmdata = fontdata[tfmdata]
- end
- local properties = tfmdata.properties
- local privates = properties and properties.privates
- return privates and privates[name] or false
-end
-
--- relatively new:
-
-do
-
- local extraprivates = { }
-
- function fonts.helpers.addextraprivate(name,f)
- extraprivates[#extraprivates+1] = { name, f }
- end
-
- local function addextraprivates(tfmdata)
- for i=1,#extraprivates do
- local e = extraprivates[i]
- local c = e[2](tfmdata)
- if c then
- fonts.helpers.addprivate(tfmdata, e[1], c)
- end
- end
- end
-
- constructors.newfeatures.otf.register {
- name = "extraprivates",
- description = "extra privates",
- default = true,
- manipulators = {
- base = addextraprivates,
- node = addextraprivates,
- }
- }
-
-end
-
-implement {
- name = "getprivatechar",
- arguments = "string",
- actions = function(name)
- local p = getprivateslot(name)
- if p then
- context(utfchar(p))
- end
- end
-}
-
-implement {
- name = "getprivatemathchar",
- arguments = "string",
- actions = function(name)
- local p = getprivateslot(family_font(0),name)
- if p then
- context(utfchar(p))
- end
- end
-}
-
-implement {
- name = "getprivateslot",
- arguments = "string",
- actions = function(name)
- local p = getprivateslot(name)
- if p then
- context(p)
- end
- end
-}
-
--- requested for latex but not supported unless really needed in context:
---
--- registerotffeature {
--- name = "ignoremathconstants",
--- description = "ignore math constants table",
--- initializers = {
--- base = function(tfmdata,value)
--- if value then
--- tfmdata.mathparameters = nil
--- end
--- end
--- }
--- }
-
--- tfmdata.properties.mathnolimitsmode = tonumber(value) or 0
-
-do
-
- local splitter = lpeg.splitat(",",tonumber)
- local lpegmatch = lpeg.match
-
- local function initialize(tfmdata,value)
- local mathparameters = tfmdata.mathparameters
- if mathparameters then
- local sup, sub
- if type(value) == "string" then
- sup, sub = lpegmatch(splitter,value)
- if not sup then
- sub, sup = 0, 0
- elseif not sub then
- sub, sup = sup, 0
- end
- elseif type(value) == "number" then
- sup, sub = 0, value
- end
- mathparameters.NoLimitSupFactor = sup
- mathparameters.NoLimitSubFactor = sub
- end
- end
-
- registerotffeature {
- name = "mathnolimitsmode",
- description = "influence nolimits placement",
- initializers = {
- base = initialize,
- node = initialize,
- }
- }
-
-end
-
-do
-
- local function initialize(tfmdata,value)
- local properties = tfmdata.properties
- if properties then
- properties.identity = value == "vertical" and "vertical" or "horizontal"
- end
- end
-
- registerotffeature {
- name = "identity",
- description = "set font identity",
- initializers = {
- base = initialize,
- node = initialize,
- }
- }
-
- local function initialize(tfmdata,value)
- local properties = tfmdata.properties
- if properties then
- properties.writingmode = value == "vertical" and "vertical" or "horizontal"
- end
- end
-
- registerotffeature {
- name = "writingmode",
- description = "set font direction",
- initializers = {
- base = initialize,
- node = initialize,
- }
- }
-
-end
-
-do -- another hack for a crappy font
-
- local function additalictowidth(tfmdata,key,value)
- local characters = tfmdata.characters
- local additions = { }
- for unicode, old_c in next, characters do
- -- maybe check for math
- local oldwidth = old_c.width
- local olditalic = old_c.italic
- if olditalic and olditalic ~= 0 then
- local private = getprivate(tfmdata)
- local new_c = {
- width = oldwidth + olditalic,
- height = old_c.height,
- depth = old_c.depth,
- commands = {
- -- { "slot", 1, private },
- -- { "slot", 0, private },
- { "char", private },
- { "right", olditalic },
- },
- }
- setmetatableindex(new_c,old_c)
- characters[unicode] = new_c
- additions[private] = old_c
- end
- end
- for k, v in next, additions do
- characters[k] = v
- end
- end
-
- registerotffeature {
- name = "italicwidths",
- description = "add italic to width",
- manipulators = {
- base = additalictowidth,
- -- node = additalictowidth, -- only makes sense for math
- }
- }
-
-end
-
-do
-
- local tounicode = fonts.mappings.tounicode
-
- local function check(tfmdata,key,value)
- if value == "ligatures" then
- local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000
- local collected = fonts.handlers.otf.readers.getcomponents(tfmdata.shared.rawdata)
- if collected and next(collected)then
- for unicode, char in next, tfmdata.characters do
- if true then -- if unicode >= private or (unicode >= 0xE000 and unicode <= 0xF8FF) then
- local u = collected[unicode]
- if u then
- local n = #u
- for i=1,n do
- if u[i] > private then
- n = 0
- break
- end
- end
- if n > 0 then
- if n == 1 then
- u = u[1]
- end
- char.unicode = u
- char.tounicode = tounicode(u)
- end
- end
- end
- end
- end
- end
- end
-
- -- forceunicodes=ligatures : aggressive lig resolving (e.g. for emoji)
- --
- -- kind of like: \enabletrackers[fonts.mapping.forceligatures]
-
- registerotffeature {
- name = "forceunicodes",
- description = "forceunicodes",
- manipulators = {
- base = check,
- node = check,
- }
- }
-
-end
-
-do
-
- -- This is a rather special test-only feature that I added for the sake of testing
- -- Idris's husayni. We wanted to know if uniscribe obeys the order of lookups in a
- -- font, in spite of what the description of handling arabic suggests. And indeed,
- -- mixed-in lookups of other features (like all these ss* in husayni) are handled
- -- the same in context as in uniscribe. If one sets reorderlookups=arab then we sort
- -- according to the "assumed" order so e.g. the ss* move to after the standard
- -- features. The observed difference in rendering is an indication that uniscribe is
- -- quite faithful to the font (while e.g. tests with the hb plugin demonstrate some
- -- interference, apart from some hard coded init etc expectations). Anyway, it means
- -- that we're okay with the (generic) node processor. A pitfall is that in context
- -- we can actually control more, so we can trigger an analyze pass with e.g.
- -- dflt/dflt while the libraries depend on the script settings for that. Uniscribe
- -- probably also parses the string and when seeing arabic will follow a different
- -- code path, although it seems to treat all features equal.
-
- local trace_reorder = trackers.register("fonts.reorderlookups",function(v) trace_reorder = v end)
- local report_reorder = logs.reporter("fonts","reorder")
-
- local vectors = { }
-
- vectors.arab = {
- gsub = {
- ccmp = 1,
- isol = 2,
- fina = 3,
- medi = 4,
- init = 5,
- rlig = 6,
- rclt = 7,
- calt = 8,
- liga = 9,
- dlig = 10,
- cswh = 11,
- mset = 12,
- },
- gpos = {
- curs = 1,
- kern = 2,
- mark = 3,
- mkmk = 4,
- },
- }
-
- function otf.reorderlookups(tfmdata,vector)
- local order = vectors[vector]
- if not order then
- return
- end
- local oldsequences = tfmdata.resources.sequences
- if oldsequences then
- local sequences = { }
- for i=1,#oldsequences do
- sequences[i] = oldsequences[i]
- end
- for i=1,#sequences do
- local s = sequences[i]
- local features = s.features
- local kind = s.type
- local index = s.index
- if features then
- local when
- local what
- for feature in sortedhash(features) do
- if not what then
- what = find(kind,"^gsub") and "gsub" or "gpos"
- end
- local newwhen = order[what][feature]
- if not newwhen then
- -- skip
- elseif not when then
- when = newwhen
- elseif newwhen < when then
- when = newwhen
- end
- end
- s.ondex = s.index
- s.index = i
- s.what = what == "gsub" and 1 or 2
- s.when = when or 99
- else
- s.ondex = s.index
- s.index = i
- s.what = 1
- s.when = 99
- end
- end
- sort(sequences,function(a,b)
- local what_a = a.what
- local what_b = b.what
- if what_a ~= what_b then
- return a.index < b.index
- end
- local when_a = a.when
- local when_b = b.when
- if when_a == when_b then
- return a.index < b.index
- else
- return when_a < when_b
- end
- end)
- local swapped = 0
- for i=1,#sequences do
- local sequence = sequences[i]
- local features = sequence.features
- if features then
- local index = sequence.index
- if index ~= i then
- swapped = swapped + 1
- end
- if trace_reorder then
- if swapped == 1 then
- report_reorder()
- report_reorder("start swapping lookups in font %!font:name!",tfmdata)
- report_reorder()
- report_reorder("gsub order: % t",table.swapped(order.gsub))
- report_reorder("gpos order: % t",table.swapped(order.gpos))
- report_reorder()
- end
- report_reorder("%03i : lookup %03i, type %s, sorted %2i, moved %s, % t",
- i,index,sequence.what == 1 and "gsub" or "gpos",sequence.when or 99,
- (index > i and "-") or (index < i and "+") or "=",sortedkeys(features))
- end
- end
- sequence.what = nil
- sequence.when = nil
- sequence.index = sequence.ondex
- end
- if swapped > 0 then
- if trace_reorder then
- report_reorder()
- report_reorder("stop swapping lookups, %i lookups swapped",swapped)
- report_reorder()
- end
--- tfmdata.resources.sequences = sequences
- tfmdata.shared.reorderedsequences = sequences
- end
- end
- end
-
- -- maybe delay till ra is filled
-
- local function reorderlookups(tfmdata,key,value)
- if value then
- otf.reorderlookups(tfmdata,value)
- end
- end
-
- registerotffeature {
- name = "reorderlookups",
- description = "reorder lookups",
- manipulators = {
- base = reorderlookups,
- node = reorderlookups,
- }
- }
-
-end
-
--- maybe useful
-
-local function initializeoutline(tfmdata,value)
- value = tonumber(value)
- if not value then
- value = 0
- else
- value = tonumber(value) or 0
- end
- if value then
- value = value * 1000
- end
- tfmdata.parameters.mode = 1
- tfmdata.parameters.width = value
-end
-
-local outline_specification = {
- name = "outline",
- description = "outline glyphs",
- initializers = {
- base = initializeoutline,
- node = initializeoutline,
- }
-}
-
-registerotffeature(outline_specification)
-registerafmfeature(outline_specification)
-
--- definitely ugly
-
-local report_effect = logs.reporter("fonts","effect")
-local trace_effect = false
-
-trackers.register("fonts.effect", function(v) trace_effect = v end)
-
-local effects = {
- inner = 0,
- normal = 0,
- outer = 1,
- outline = 1,
- both = 2,
- hidden = 3,
-}
-
-local function initializeeffect(tfmdata,value)
- local spec
- if type(value) == "number" then
- spec = { width = value }
- else
- spec = settings_to_hash(value)
- end
- local effect = spec.effect or "both"
- local width = tonumber(spec.width) or 0
- local mode = effects[effect]
- if not mode then
- report_effect("invalid effect %a",effect)
- elseif width == 0 and mode == 0 then
- report_effect("invalid width %a for effect %a",width,effect)
- else
- local parameters = tfmdata.parameters
- local properties = tfmdata.properties
- parameters.mode = mode
- parameters.width = width * 1000
- local factor = tonumber(spec.factor) or 0
- local hfactor = tonumber(spec.vfactor) or factor
- local vfactor = tonumber(spec.hfactor) or factor
- local delta = tonumber(spec.delta) or 1
- local wdelta = tonumber(spec.wdelta) or delta
- local hdelta = tonumber(spec.hdelta) or delta
- local ddelta = tonumber(spec.ddelta) or hdelta
- properties.effect = {
- effect = effect,
- width = width,
- factor = factor,
- hfactor = hfactor,
- vfactor = vfactor,
- wdelta = wdelta,
- hdelta = hdelta,
- ddelta = ddelta,
- }
- end
-end
-
-local function manipulateeffect(tfmdata)
- local effect = tfmdata.properties.effect
- if effect then
- local characters = tfmdata.characters
- local parameters = tfmdata.parameters
- local multiplier = effect.width * 100
- local wdelta = effect.wdelta * parameters.hfactor * multiplier
- local hdelta = effect.hdelta * parameters.vfactor * multiplier
- local ddelta = effect.ddelta * parameters.vfactor * multiplier
- local hshift = wdelta / 2
- local factor = (1 + effect.factor) * parameters.factor
- local hfactor = (1 + effect.hfactor) * parameters.hfactor
- local vfactor = (1 + effect.vfactor) * parameters.vfactor
- for unicode, old_c in next, characters do
- local oldwidth = old_c.width
- local oldheight = old_c.height
- local olddepth = old_c.depth
- if oldwidth and oldwidth > 0 then
- old_c.width = oldwidth + wdelta
- old_c.commands = {
- { "right", hshift },
- { "char", unicode },
- }
- end
- if oldheight and oldheight > 0 then
- old_c.height = oldheight + hdelta
- end
- if olddepth and olddepth > 0 then
- old_c.depth = olddepth + ddelta
- end
- end
- parameters.factor = factor
- parameters.hfactor = hfactor
- parameters.vfactor = vfactor
- if trace_effect then
- report_effect("applying effect")
- report_effect(" effect : %s", effect.effect)
- report_effect(" width : %s => %s", effect.width, multiplier)
- report_effect(" factor : %s => %s", effect.factor, factor )
- report_effect(" hfactor : %s => %s", effect.hfactor,hfactor)
- report_effect(" vfactor : %s => %s", effect.vfactor,vfactor)
- report_effect(" wdelta : %s => %s", effect.wdelta, wdelta)
- report_effect(" hdelta : %s => %s", effect.hdelta, hdelta)
- report_effect(" ddelta : %s => %s", effect.ddelta, ddelta)
- end
- end
-end
-
-local effect_specification = {
- name = "effect",
- description = "apply effects to glyphs",
- initializers = {
- base = initializeeffect,
- node = initializeeffect,
- },
- manipulators = {
- base = manipulateeffect,
- node = manipulateeffect,
- },
-}
-
-registerotffeature(effect_specification)
-registerafmfeature(effect_specification)
diff --git a/tex/context/base/mkiv/font-fbk.lua b/tex/context/base/mkiv/font-fbk.lua
index 79ebc3f25..122e43ddc 100644
--- a/tex/context/base/mkiv/font-fbk.lua
+++ b/tex/context/base/mkiv/font-fbk.lua
@@ -14,38 +14,38 @@ local next = next
<p>This is very experimental code!</p>
--ldx]]--
-local trace_combining_visualize = false trackers.register("fonts.composing.visualize", function(v) trace_combining_visualize = v end)
-local trace_combining_define = false trackers.register("fonts.composing.define", function(v) trace_combining_define = v end)
+local trace_visualize = false trackers.register("fonts.composing.visualize", function(v) trace_visualize = v end)
+local trace_define = false trackers.register("fonts.composing.define", function(v) trace_define = v end)
-trackers.register("fonts.combining", "fonts.composing.define") -- for old times sake (and manuals)
-trackers.register("fonts.combining.all", "fonts.composing.*") -- for old times sake (and manuals)
-
-local report_combining = logs.reporter("fonts","combining")
-
-local force_combining = false -- just for demo purposes (see mk)
+local report = logs.reporter("fonts","combining")
local allocate = utilities.storage.allocate
local fonts = fonts
local handlers = fonts.handlers
local constructors = fonts.constructors
+local helpers = fonts.helpers
local otf = handlers.otf
local afm = handlers.afm
local registerotffeature = otf.features.register
local registerafmfeature = afm.features.register
+local addotffeature = otf.addfeature
+
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 vfcommands = helpers.commands
+local charcommand = vfcommands.char
+local rightcommand = vfcommands.right
+local downcommand = vfcommands.down
+local upcommand = vfcommands.up
+local push = vfcommands.push
+local pop = vfcommands.pop
-local force_composed = false
-local cache = { } -- we could make these weak
-local fraction = 0.15 -- 30 units for lucida
+local force_combining = false -- just for demo purposes (see mk)
+local fraction = 0.15 -- 30 units for lucida
-- todo: we also need to update the feature hashes ... i'll do that when i'm in the mood
-- and/or when i need it
@@ -65,15 +65,15 @@ local function composecharacters(tfmdata)
local italicfactor = parameters.italicfactor or 0
local vfspecials = backends.tables.vfspecials --brr
local red, green, blue, black
- if trace_combining_visualize then
+ if trace_visualize then
red = vfspecials.startcolor("red")
green = vfspecials.startcolor("green")
blue = vfspecials.startcolor("blue")
black = vfspecials.stopcolor
end
local compose = fonts.goodies.getcompositions(tfmdata)
- if compose and trace_combining_visualize then
- report_combining("using compose information from goodies file")
+ if compose and trace_visualize then
+ report("using compose information from goodies file")
end
local done = false
for i, c in next, unicodecharacters do -- loop over all characters ... not that efficient but a specials hash takes memory
@@ -105,31 +105,25 @@ local function composecharacters(tfmdata)
acc = unicodefallbacks[acc]
charsacc = acc and characters[acc]
end
- local chr_t = cache[chr]
- if not chr_t then
- -- chr_t = { "slot", 1, chr }
- -- chr_t = { "slot", 0, chr }
- chr_t = { "char", chr }
- cache[chr] = chr_t
- end
+ local chr_t = charcommand[chr]
if charsacc then
- if trace_combining_define then
- report_combining("composed %C, base %C, accent %C",i,chr,acc)
- end
- local acc_t = cache[acc]
- if not acc_t then
- -- acc_t = { "slot", 1, acc }
- -- acc_t = { "slot", 0, acc }
- acc_t = { "char", acc }
- cache[acc] = acc_t
+ if trace_define then
+ report("composed %C, base %C, accent %C",i,chr,acc)
end
+ local acc_t = charcommand[acc]
local cb = descriptions[chr].boundingbox
local ab = descriptions[acc].boundingbox
-- todo: adapt height
if cb and ab then
- local c_llx, c_lly, c_urx, c_ury = scale*cb[1], scale*cb[2], scale*cb[3], scale*cb[4]
- local a_llx, a_lly, a_urx, a_ury = scale*ab[1], scale*ab[2], scale*ab[3], scale*ab[4]
- local done = false
+ local c_llx = scale*cb[1]
+ local c_lly = scale*cb[2]
+ local c_urx = scale*cb[3]
+ local c_ury = scale*cb[4]
+ local a_llx = scale*ab[1]
+ local a_lly = scale*ab[2]
+ local a_urx = scale*ab[3]
+ local a_ury = scale*ab[4]
+ local done = false
if compose then
local i_compose = compose[i]
local i_anchored = i_compose and i_compose.anchored
@@ -148,26 +142,30 @@ local function composecharacters(tfmdata)
local ay = a_anchor.y or 0
local dx = cx - ax
local dy = cy - ay
- if trace_combining_define then
- report_combining("building %C from %C and %C",i,chr,acc)
- report_combining(" boundingbox:")
- report_combining(" chr: %3i %3i %3i %3i",unpack(cb))
- report_combining(" acc: %3i %3i %3i %3i",unpack(ab))
- report_combining(" anchors:")
- report_combining(" chr: %3i %3i",cx,cy)
- report_combining(" acc: %3i %3i",ax,ay)
- report_combining(" delta:")
- report_combining(" %s: %3i %3i",i_anchored,dx,dy)
+ if trace_define then
+ report("building %C from %C and %C",i,chr,acc)
+ report(" boundingbox:")
+ report(" chr: %3i %3i %3i %3i",unpack(cb))
+ report(" acc: %3i %3i %3i %3i",unpack(ab))
+ report(" anchors:")
+ report(" chr: %3i %3i",cx,cy)
+ report(" acc: %3i %3i",ax,ay)
+ report(" delta:")
+ report(" %s: %3i %3i",i_anchored,dx,dy)
end
- if trace_combining_visualize then
- t.commands = { push, {"right", scale*dx}, {"down",-scale*dy}, green, acc_t, black, pop, chr_t }
- -- t.commands = {
- -- push, {"right", scale*cx}, {"down", -scale*cy}, red, {"rule",10000,10000,10000}, pop,
- -- push, {"right", scale*ax}, {"down", -scale*ay}, blue, {"rule",10000,10000,10000}, pop,
- -- push, {"right", scale*dx}, {"down", -scale*dy}, green, acc_t, black, pop, chr_t
- -- }
+ local right = rightcommand[scale*dx]
+ local down = upcommand[scale*dy]
+ if trace_visualize then
+ t.commands = {
+ push, right, down,
+ green, acc_t, black,
+ pop, chr_t,
+ }
else
- t.commands = { push, {"right", scale*dx}, {"down",-scale*dy}, acc_t, pop, chr_t }
+ t.commands = {
+ push, right, down,
+ acc_t, pop, chr_t,
+ }
end
done = true
end
@@ -179,10 +177,17 @@ local function composecharacters(tfmdata)
local dx = (c_urx - a_urx - a_llx + c_llx)/2
local dd = (c_urx - c_llx)*italicfactor
if a_ury < 0 then
- if trace_combining_visualize then
- t.commands = { push, {"right", dx-dd}, red, acc_t, black, pop, chr_t }
+ local right = rightcommand[dx-dd]
+ if trace_visualize then
+ t.commands = {
+ push, right, red, acc_t,
+ black, pop, chr_t,
+ }
else
- t.commands = { push, {"right", dx-dd}, acc_t, pop, chr_t }
+ t.commands = {
+ push, right, acc_t, pop,
+ chr_t,
+ }
end
elseif c_ury > a_lly then -- messy test
local dy
@@ -214,27 +219,46 @@ local function composecharacters(tfmdata)
else
dy = - deltaxheight + extraxheight
end
- if trace_combining_visualize then
- t.commands = { push, { "right", dx+dd }, { "down", dy }, green, acc_t, black, pop, chr_t }
+ local right = rightcommand[dx+dd]
+ local down = downcommand[dy]
+ if trace_visualize then
+ t.commands = {
+ push, right, down, green,
+ acc_t, black, pop, chr_t,
+ }
else
- t.commands = { push, { "right", dx+dd }, { "down", dy }, acc_t, pop, chr_t }
+ t.commands = {
+ push, right, down, acc_t,
+ pop, chr_t,
+ }
end
else
- if trace_combining_visualize then
- t.commands = { push, { "right", dx+dd }, blue, acc_t, black, pop, chr_t }
+ local right = rightcommand[dx+dd]
+ if trace_visualize then
+ t.commands = {
+ push, right, blue, acc_t,
+ black, pop, chr_t,
+ }
else
- t.commands = { push, { "right", dx+dd }, acc_t, pop, chr_t }
+ t.commands = {
+ push, right, acc_t, pop,
+ chr_t,
+ }
end
end
end
else
- t.commands = { chr_t } -- else index mess
+ t.commands = {
+ chr_t, -- else index mess
+ }
end
else
- if trace_combining_define then
- report_combining("%C becomes simplified %C",i,chr)
+ if trace_define then
+ report("%C becomes simplified %C",i,chr)
end
- t.commands = { chr_t } -- else index mess
+ t.commands = {
+ chr_t, -- else index mess
+ }
end
done = true
characters[i] = t
@@ -254,7 +278,7 @@ local function composecharacters(tfmdata)
end
end
-local compose_specification = {
+local specification = {
name = "compose",
description = "additional composed characters",
manipulators = {
@@ -263,75 +287,71 @@ local compose_specification = {
}
}
-registerotffeature(compose_specification)
-registerafmfeature(compose_specification)
+registerotffeature(specification)
+registerafmfeature(specification)
-vf.helpers.composecharacters = composecharacters
+addotffeature {
+ name = "char-ligatures",
+ type = "ligature",
+ data = characters.splits.char,
+ order = { "char-ligatures" },
+ prepend = true,
+}
--- This installs the builder into the regular virtual font builder,
--- which only makes sense as demo.
+addotffeature {
+ name = "compat-ligatures",
+ type = "ligature",
+ data = characters.splits.compat,
+ order = { "compat-ligatures" },
+ prepend = true,
+}
-commands["compose.trace.enable"] = function()
- trace_combining_visualize = true
-end
+registerotffeature {
+ name = 'char-ligatures',
+ description = 'unicode char specials to ligatures',
+}
-commands["compose.trace.disable"] = function()
- trace_combining_visualize = false
-end
+registerotffeature {
+ name = 'compat-ligatures',
+ description = 'unicode compat specials to ligatures',
+}
-commands["compose.force.enable"] = function()
- force_combining = true
-end
+do
-commands["compose.force.disable"] = function()
- force_combining = false
-end
+ -- This installs the builder into the regular virtual font builder,
+ -- which only makes sense as demo.
-commands["compose.trace.set"] = function(g,v)
- if v[2] == nil then
- trace_combining_visualize = true
- else
- trace_combining_visualize = v[2]
- end
-end
-
-commands["compose.apply"] = function(g,v)
- composecharacters(g)
-end
+ local vf = handlers.vf
+ local commands = vf.combiner.commands
--- vf builder
+ vf.helpers.composecharacters = composecharacters
--- { "pdf", "origin", "q " .. s .. " 0 0 " .. s .. " 0 0 cm" },
--- { "pdf", "origin", "q 1 0 0 1 " .. -w .. " " .. -h .. " cm" },
--- { "pdf", "origin", "/Fm\XX\space Do" },
--- { "pdf", "origin", "Q" },
--- { "pdf", "origin", "Q" },
+ commands["compose.trace.enable"] = function()
+ trace_visualize = true
+ end
--- new and experimental
+ commands["compose.trace.disable"] = function()
+ trace_visualize = false
+ end
-local everywhere = { ["*"] = { ["*"] = true } } -- or: { ["*"] = { "*" } }
-local noflags = { }
+ commands["compose.force.enable"] = function()
+ force_combining = true
+ end
-local char_specification = {
- type = "ligature",
- features = everywhere,
- data = characters.splits.char,
- order = { "char-ligatures" },
- flags = noflags,
- prepend = true,
-}
+ commands["compose.force.disable"] = function()
+ force_combining = false
+ end
-local compat_specification = {
- type = "ligature",
- features = everywhere,
- data = characters.splits.compat,
- order = { "compat-ligatures" },
- flags = noflags,
- prepend = true,
-}
+ commands["compose.trace.set"] = function(g,v)
+ if v[2] == nil then
+ trace_visualize = true
+ else
+ trace_visualize = v[2]
+ end
+ end
-otf.addfeature("char-ligatures", char_specification) -- xlig (extra)
-otf.addfeature("compat-ligatures",compat_specification) -- plig (pseudo)
+ commands["compose.apply"] = function(g,v)
+ composecharacters(g)
+ end
-registerotffeature { name = 'char-ligatures', description = 'unicode char specials to ligatures' }
-registerotffeature { name = 'compat-ligatures', description = 'unicode compat specials to ligatures' }
+end
diff --git a/tex/context/base/mkiv/font-fea.mkvi b/tex/context/base/mkiv/font-fea.mkvi
index 5f65543ab..4a5356090 100644
--- a/tex/context/base/mkiv/font-fea.mkvi
+++ b/tex/context/base/mkiv/font-fea.mkvi
@@ -368,11 +368,19 @@
% \doifelsecurrentfonthasfeature{crap}{YES}{NO}
% \doifelsecurrentfonthasfeature{kern}{YES}{NO}
-\def\doifelsecurrentfonthasfeature#feature%
+\def\doifelsecurrentfonthasfeature#feature% expandable
{\clf_doifelsecurrentfonthasfeature{#feature}}
\let\doifcurrentfonthasfeatureelse\doifelsecurrentfonthasfeature
+\def\doifelsefontfeature#feature% expandable
+ {\clf_doifelsefontfeature{#feature}}
+
+\let\doiffontfeatureelse\doifelsefontfeature
+
+\def\doifunknownfontfeature#feature% expandable
+ {\clf_doifunknownfontfeature{#feature}}
+
% new:
\clf_registerlanguagefeatures
diff --git a/tex/context/base/mkiv/font-fil.mkvi b/tex/context/base/mkiv/font-fil.mkvi
index 01fa4a338..16ce57f8a 100644
--- a/tex/context/base/mkiv/font-fil.mkvi
+++ b/tex/context/base/mkiv/font-fil.mkvi
@@ -42,19 +42,17 @@
%
% \setupbodyfont[palatino]
-\let\fontclass\empty
-
\unexpanded\def\startfontclass
{\dosingleempty\font_basics_start_font_class}
\def\font_basics_start_font_class[#class]%
- {\pushmacro\fontclass
+ {\push_macro_fontclass
\doifelse{#class}\v!each
{\let\fontclass\empty}
{\doifsomething{#class}{\def\fontclass{#class}}}}
\unexpanded\def\stopfontclass
- {\popmacro\fontclass}
+ {\pop_macro_fontclass}
\def\classfont#class#name{#class#name} % \definefont[whatever][\classfont{xx}{yy} at 10pt]
@@ -109,11 +107,14 @@
\let\p_designsize\undefined
\expandafter\font_basics_get_font_parameter_yes#specification,]=,}
+% todo: check if we can use \edef but then we need to protect \mathsizesuffix .. in fact that
+% can be default then: \let\mathsizesuffix\relax .. i need to play with it first
+
\def\font_basics_get_font_parameter_nop#key=#value,%
{\if]#key%
\font_basics_get_font_parameter_nop_finish
\else
- \expandafter\normaldef\csname p_#key\endcsname{#value}%
+ \expandafter\normaldef\csname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix
\expandafter\font_basics_get_font_parameter_nop
\fi}
@@ -121,13 +122,13 @@
{\if]#key%
\font_basics_get_font_parameter_yes_finish
\else
- \expandafter\normaldef\csname p_#key\endcsname{#value}%
+ \expandafter\normaldef\csname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix
\expandafter\font_basics_get_font_parameter_yes
\fi}
% helpers, some day these will be toks and counts
-% \def\fntsetdefname {\global\let\somefontname\defaultfontfile}
+% \def\fntsetdefname {\glet\somefontname\defaultfontfile}
% \def\fntsetsomename{\gdef\somefontname} % takes argument
% \def\fntsetnopsize {\let\somefontsize\empty}
% \def\fntsetsomesize{\def\somefontsize} % takes argument
@@ -145,10 +146,10 @@
\expandafter\let\csname\??fontfile\m_font_name\s!designsize\endcsname\undefined}
\def\font_basics_define_font_synonym_yes_nil
- {\global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\undefined
- \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\undefined
- \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\undefined
- \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\undefined}
+ {\expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\undefined
+ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\undefined
+ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\undefined
+ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\undefined}
\def\font_basics_get_font_parameter_nop_finish
{\expandafter\let\csname\??fontfile\m_font_name\s!features \endcsname\p_features
@@ -157,10 +158,10 @@
\expandafter\let\csname\??fontfile\m_font_name\s!designsize\endcsname\p_designsize}
\def\font_basics_get_font_parameter_yes_finish
- {\global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\p_features
- \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\p_fallbacks
- \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\p_goodies
- \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\p_designsize}
+ {\expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\p_features
+ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\p_fallbacks
+ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\p_goodies
+ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\p_designsize}
%\definefontsynonym [KopFont] [\fontclassname{officina}{SerifBold}]
%
@@ -306,6 +307,8 @@
#2%
\fi\fi}
+\installmacrostack\fontclass
+
%D Files or names can have properties and these need to be consulted
%D at some point. They can inherit them.
diff --git a/tex/context/base/mkiv/font-gbn.lua b/tex/context/base/mkiv/font-gbn.lua
deleted file mode 100644
index 8f1acac65..000000000
--- a/tex/context/base/mkiv/font-gbn.lua
+++ /dev/null
@@ -1,262 +0,0 @@
-if not modules then modules = { } end modules ['font-gbn'] = {
- version = 1.001,
- comment = "companion to luatex-*.tex",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- generic [base|node] mode handler
-
-if context then
- texio.write_nl("fatal error: this module is not for context")
- os.exit()
-end
-
-local next = next
-
-local fonts = fonts
-local nodes = nodes
-
-local nuts = nodes.nuts -- context abstraction of direct nodes
-
-local traverse_id = nuts.traverse_id
-local flush_node = nuts.flush_node
-
-local glyph_code = nodes.nodecodes.glyph
-local disc_code = nodes.nodecodes.disc
-
-local tonode = nuts.tonode
-local tonut = nuts.tonut
-
-local getfont = nuts.getfont
-local getchar = nuts.getchar
-local getid = nuts.getid
-local getboth = nuts.getboth
-local getprev = nuts.getprev
-local getnext = nuts.getnext
-local getdisc = nuts.getdisc
-local setchar = nuts.setchar
-local setlink = nuts.setlink
-local setprev = nuts.setprev
-
--- from now on we apply ligaturing and kerning here because it might interfere with complex
--- opentype discretionary handling where the base ligature pass expect some weird extra
--- pointers (which then confuse the tail slider that has some checking built in)
-
-local n_ligaturing = node.ligaturing
-local n_kerning = node.kerning
-
-local ligaturing = nuts.ligaturing
-local kerning = nuts.kerning
-
-local basemodepass = true
-
-local function l_warning() texio.write_nl("warning: node.ligaturing called directly") l_warning = nil end
-local function k_warning() texio.write_nl("warning: node.kerning called directly") k_warning = nil end
-
-function node.ligaturing(...)
- if basemodepass and l_warning then
- l_warning()
- end
- return n_ligaturing(...)
-end
-
-function node.kerning(...)
- if basemodepass and k_warning then
- k_warning()
- end
- return n_kerning(...)
-end
-
-function nodes.handlers.setbasemodepass(v)
- basemodepass = v
-end
-
--------- nodes.handlers.nodepass(head)
-function nodes.handlers.nodepass(head,groupcode,size,packtype,direction)
- local fontdata = fonts.hashes.identifiers
- if fontdata then
- local nuthead = tonut(head)
- local usedfonts = { }
- local basefonts = { }
- local prevfont = nil
- local basefont = nil
- local variants = nil
- local redundant = nil
- local nofused = 0
- for n in traverse_id(glyph_code,nuthead) do
- local font = getfont(n)
- if font ~= prevfont then
- if basefont then
- basefont[2] = getprev(n)
- end
- prevfont = font
- local used = usedfonts[font]
- if not used then
- local tfmdata = fontdata[font] --
- if tfmdata then
- local shared = tfmdata.shared -- we need to check shared, only when same features
- if shared then
- local processors = shared.processes
- if processors and #processors > 0 then
- usedfonts[font] = processors
- nofused = nofused + 1
- elseif basemodepass then
- basefont = { n, nil }
- basefonts[#basefonts+1] = basefont
- end
- end
- local resources = tfmdata.resources
- variants = resources and resources.variants
- variants = variants and next(variants) and variants or false
- end
- else
- local tfmdata = fontdata[prevfont]
- if tfmdata then
- local resources = tfmdata.resources
- variants = resources and resources.variants
- variants = variants and next(variants) and variants or false
- end
- end
- end
- if variants then
- local char = getchar(n)
- if char >= 0xFE00 and (char <= 0xFE0F or (char >= 0xE0100 and char <= 0xE01EF)) then
- local hash = variants[char]
- if hash then
- local p = getprev(n)
- if p and getid(p) == glyph_code then
- local variant = hash[getchar(p)]
- if variant then
- setchar(p,variant)
- end
- end
- end
- -- per generic user request we always remove selectors
- if not redundant then
- redundant = { n }
- else
- redundant[#redundant+1] = n
- end
- end
- end
- end
- local nofbasefonts = #basefonts
- if redundant then
- for i=1,#redundant do
- local r = redundant[i]
- local p, n = getboth(r)
- if r == nuthead then
- nuthead = n
- setprev(n)
- else
- setlink(p,n)
- end
- if nofbasefonts > 0 then
- for i=1,nofbasefonts do
- local bi = basefonts[i]
- if r == bi[1] then
- bi[1] = n
- end
- if r == bi[2] then
- bi[2] = n
- end
- end
- end
- flush_node(r)
- end
- end
- for d in traverse_id(disc_code,nuthead) do
- local _, _, r = getdisc(d)
- if r then
- for n in traverse_id(glyph_code,r) do
- local font = getfont(n)
- if font ~= prevfont then
- prevfont = font
- local used = usedfonts[font]
- if not used then
- local tfmdata = fontdata[font] --
- if tfmdata then
- local shared = tfmdata.shared -- we need to check shared, only when same features
- if shared then
- local processors = shared.processes
- if processors and #processors > 0 then
- usedfonts[font] = processors
- nofused = nofused + 1
- end
- end
- end
- end
- end
- end
- end
- end
- if next(usedfonts) then
- for font, processors in next, usedfonts do
- for i=1,#processors do
- head = processors[i](head,font,0,direction,nofused) or head
- end
- end
- end
- if basemodepass and nofbasefonts > 0 then
- for i=1,nofbasefonts do
- local range = basefonts[i]
- local start = range[1]
- local stop = range[2]
- if start then
- local front = nuthead == start
- local prev, next
- if stop then
- next = getnext(stop)
- start, stop = ligaturing(start,stop)
- start, stop = kerning(start,stop)
- else
- prev = getprev(start)
- start = ligaturing(start)
- start = kerning(start)
- end
- if prev then
- setlink(prev,start)
- end
- if next then
- setlink(stop,next)
- end
- if front and nuthead ~= start then
- head = tonode(start)
- end
- end
- end
- end
- return head, true
- else
- return head, false
- end
-end
-
-function nodes.handlers.basepass(head)
- if basemodepass then
- head = n_ligaturing(head)
- head = n_kerning(head)
- end
- return head, true
-end
-
-local nodepass = nodes.handlers.nodepass
-local basepass = nodes.handlers.basepass
-local injectpass = nodes.injections.handler
-local protectpass = nodes.handlers.protectglyphs
-
-function nodes.simple_font_handler(head,groupcode,size,packtype,direction)
- if head then
- head = nodepass(head,groupcode,size,packtype,direction)
- head = injectpass(head)
- if not basemodepass then
- head = basepass(head)
- end
- protectpass(head)
- return head, true
- else
- return head, false
- end
-end
diff --git a/tex/context/base/mkiv/font-gds.mkvi b/tex/context/base/mkiv/font-gds.mkvi
index 549ede46f..05cf08790 100644
--- a/tex/context/base/mkiv/font-gds.mkvi
+++ b/tex/context/base/mkiv/font-gds.mkvi
@@ -62,7 +62,7 @@
%
% \definedfont[husayni*husayni-colored at 36pt]
%
-% \starttext \pardir TRT \textdir TRT
+% \starttext \righttoleft
%
% \setfontcolorscheme[1]
%
diff --git a/tex/context/base/mkiv/font-hsh.lua b/tex/context/base/mkiv/font-hsh.lua
index 60a27c043..8d1e85145 100644
--- a/tex/context/base/mkiv/font-hsh.lua
+++ b/tex/context/base/mkiv/font-hsh.lua
@@ -18,48 +18,50 @@ fonts.hashes = hashes
-- todo: autoallocate ... just create on the fly .. use constructors.keys (problem: plurals)
-local identifiers = hashes.identifiers or allocate()
-local characters = hashes.characters or allocate() -- chardata
-local descriptions = hashes.descriptions or allocate()
-local parameters = hashes.parameters or allocate()
-local properties = hashes.properties or allocate()
-local resources = hashes.resources or allocate()
-local spacings = hashes.spacings or allocate()
-local spaces = hashes.spaces or allocate()
-local quads = hashes.quads or allocate() -- maybe also spacedata
-local xheights = hashes.xheights or allocate()
-local csnames = hashes.csnames or allocate() -- namedata
-local features = hashes.features or allocate()
-local marks = hashes.marks or allocate()
-local classes = hashes.classes or allocate()
-local italics = hashes.italics or allocate()
-local lastmathids = hashes.lastmathids or allocate()
-local dynamics = hashes.dynamics or allocate()
-local unicodes = hashes.unicodes or allocate()
-local originals = hashes.originals or allocate()
-local modes = hashes.modes or allocate()
-local variants = hashes.variants or allocate()
-
-hashes.characters = characters
-hashes.descriptions = descriptions
-hashes.parameters = parameters
-hashes.properties = properties
-hashes.resources = resources
-hashes.spacings = spacings
-hashes.spaces = spaces
-hashes.quads = quads hashes.emwidths = quads
-hashes.xheights = xheights hashes.exheights = xheights
-hashes.csnames = csnames
-hashes.features = features
-hashes.marks = marks
-hashes.classes = classes
-hashes.italics = italics
-hashes.lastmathids = lastmathids
-hashes.dynamics = dynamics
-hashes.unicodes = unicodes
-hashes.originals = originals
-hashes.modes = modes
-hashes.variants = variants
+local identifiers = hashes.identifiers or allocate()
+local characters = hashes.characters or allocate() -- chardata
+local descriptions = hashes.descriptions or allocate()
+local parameters = hashes.parameters or allocate()
+local mathparameters = hashes.mathparameters or allocate()
+local properties = hashes.properties or allocate()
+local resources = hashes.resources or allocate()
+local spacings = hashes.spacings or allocate()
+local spaces = hashes.spaces or allocate()
+local quads = hashes.quads or allocate() -- maybe also spacedata
+local xheights = hashes.xheights or allocate()
+local csnames = hashes.csnames or allocate() -- namedata
+local features = hashes.features or allocate()
+local marks = hashes.marks or allocate()
+local classes = hashes.classes or allocate()
+local italics = hashes.italics or allocate()
+local lastmathids = hashes.lastmathids or allocate()
+local dynamics = hashes.dynamics or allocate()
+local unicodes = hashes.unicodes or allocate()
+local originals = hashes.originals or allocate()
+local modes = hashes.modes or allocate()
+local variants = hashes.variants or allocate()
+
+hashes.characters = characters
+hashes.descriptions = descriptions
+hashes.parameters = parameters
+hashes.mathparameters = mathparameters
+hashes.properties = properties
+hashes.resources = resources
+hashes.spacings = spacings
+hashes.spaces = spaces
+hashes.quads = quads hashes.emwidths = quads
+hashes.xheights = xheights hashes.exheights = xheights
+hashes.csnames = csnames
+hashes.features = features
+hashes.marks = marks
+hashes.classes = classes
+hashes.italics = italics
+hashes.lastmathids = lastmathids
+hashes.dynamics = dynamics
+hashes.unicodes = unicodes
+hashes.originals = originals
+hashes.modes = modes
+hashes.variants = variants
local nodepool = nodes and nodes.pool
local dummyglyph = nodepool and nodepool.register(nodepool.glyph())
@@ -68,7 +70,9 @@ local nulldata = allocate {
name = "nullfont",
characters = { },
descriptions = { },
- properties = { },
+ properties = {
+ designsize = 786432,
+ },
parameters = { -- lmromanregular @ 12pt
slantperpoint = 0,
spacing = {
@@ -87,6 +91,7 @@ local nulldata = allocate {
x_height = 338952, -- 5
quad = 786432, -- 6
extra_space = 85459, -- 7
+ size = 786432,
},
}
@@ -148,6 +153,16 @@ setmetatableindex(parameters, function(t,k)
end
end)
+setmetatableindex(mathparameters, function(t,k)
+ if k == true then
+ return mathparameters[currentfont()]
+ else
+ local mathparameters = identifiers[k].mathparameters
+ t[k] = mathparameters
+ return mathparameters
+ end
+end)
+
setmetatableindex(properties, function(t,k)
if k == true then
return properties[currentfont()]
diff --git a/tex/context/base/mkiv/font-imp-dimensions.lua b/tex/context/base/mkiv/font-imp-dimensions.lua
new file mode 100644
index 000000000..a7125625d
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-dimensions.lua
@@ -0,0 +1,115 @@
+if not modules then modules = { } end modules ['font-imp-dimensions'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not context then return end
+
+local next, type, tonumber = next, type, tonumber
+
+local fonts = fonts
+local utilities = utilities
+
+local helpers = fonts.helpers
+local prependcommands = helpers.prependcommands
+local charcommand = helpers.commands.char
+local rightcommand = helpers.commands.right
+
+local handlers = fonts.handlers
+local otf = handlers.otf
+local afm = handlers.afm
+
+local registerotffeature = otf.features.register
+local registerafmfeature = afm.features.register
+
+local settings_to_array = utilities.parsers.settings_to_array
+local gettexdimen = tex.getdimen
+
+-- For Wolfgang Schuster:
+--
+-- \definefontfeature[thisway][default][script=hang,language=zhs,dimensions={2,2,2}]
+-- \definedfont[file:kozminpr6nregular*thisway]
+
+local function initialize(tfmdata,key,value)
+ if type(value) == "string" and value ~= "" then
+ local characters = tfmdata.characters
+ local parameters = tfmdata.parameters
+ local emwidth = parameters.quad
+ local exheight = parameters.xheight
+ local newwidth = false
+ local newheight = false
+ local newdepth = false
+ if value == "strut" then
+ newheight = gettexdimen("strutht")
+ newdepth = gettexdimen("strutdp")
+ elseif value == "mono" then
+ newwidth = emwidth
+ else
+ local spec = settings_to_array(value)
+ newwidth = tonumber(spec[1])
+ newheight = tonumber(spec[2])
+ newdepth = tonumber(spec[3])
+ if newwidth then newwidth = newwidth * emwidth end
+ if newheight then newheight = newheight * exheight end
+ if newdepth then newdepth = newdepth * exheight end
+ end
+ if newwidth or newheight or newdepth then
+ for unicode, character in next, characters do
+ local oldwidth = character.width
+ local oldheight = character.height
+ local olddepth = character.depth
+ local width = newwidth or oldwidth or 0
+ local height = newheight or oldheight or 0
+ local depth = newdepth or olddepth or 0
+ if oldwidth ~= width or oldheight ~= height or olddepth ~= depth then
+ character.width = width
+ character.height = height
+ character.depth = depth
+ if oldwidth ~= width then
+ local commands = character.commands
+ local hshift = rightcommand[(width - oldwidth) / 2]
+ if commands then
+ character.commands = prependcommands (
+ commands,
+ hshift
+ )
+ else
+ character.commands = {
+ hshift,
+ charcommand[unicode],
+ }
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+local specification = {
+ name = "dimensions",
+ description = "force dimensions",
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local function initialize(tfmdata,value)
+ tfmdata.properties.realdimensions = value and true
+end
+
+registerotffeature {
+ name = "realdimensions",
+ description = "accept negative dimenions",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
diff --git a/tex/context/base/mkiv/font-imp-effects.lua b/tex/context/base/mkiv/font-imp-effects.lua
new file mode 100644
index 000000000..cc6e4c0bf
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-effects.lua
@@ -0,0 +1,414 @@
+if not modules then modules = { } end modules ['font-imp-effects'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: pickup from goodies: if type(effect) then ...
+
+local next, type, tonumber = next, type, tonumber
+local is_boolean = string.is_boolean
+
+local fonts = fonts
+
+local handlers = fonts.handlers
+local registerotffeature = handlers.otf.features.register
+local registerafmfeature = handlers.afm.features.register
+
+local settings_to_hash = utilities.parsers.settings_to_hash_colon_too
+
+local helpers = fonts.helpers
+local prependcommands = helpers.prependcommands
+local charcommand = helpers.commands.char
+local leftcommand = helpers.commands.left
+local rightcommand = helpers.commands.right
+local upcommand = helpers.commands.up
+local downcommand = helpers.commands.down
+local dummycommand = helpers.commands.dummy
+
+----- constructors = fonts.constructors
+----- getmathparameter = constructors.getmathparameter
+----- setmathparameter = constructors.setmathparameter
+
+local report_effect = logs.reporter("fonts","effect")
+local report_slant = logs.reporter("fonts","slant")
+local report_extend = logs.reporter("fonts","extend")
+local report_squeeze = logs.reporter("fonts","squeeze")
+
+local trace = false
+
+trackers.register("fonts.effect", function(v) trace = v end)
+trackers.register("fonts.slant", function(v) trace = v end)
+trackers.register("fonts.extend", function(v) trace = v end)
+trackers.register("fonts.squeeze",function(v) trace = v end)
+
+local function initializeslant(tfmdata,value)
+ value = tonumber(value)
+ if not value then
+ value = 0
+ elseif value > 1 then
+ value = 1
+ elseif value < -1 then
+ value = -1
+ end
+ if trace then
+ report_slant("applying %0.3f",value)
+ end
+ tfmdata.parameters.slantfactor = value
+end
+
+local specification = {
+ name = "slant",
+ description = "slant glyphs",
+ initializers = {
+ base = initializeslant,
+ node = initializeslant,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local function initializeextend(tfmdata,value)
+ value = tonumber(value)
+ if not value then
+ value = 0
+ elseif value > 10 then
+ value = 10
+ elseif value < -10 then
+ value = -10
+ end
+ if trace then
+ report_extend("applying %0.3f",value)
+ end
+ tfmdata.parameters.extendfactor = value
+end
+
+local specification = {
+ name = "extend",
+ description = "scale glyphs horizontally",
+ initializers = {
+ base = initializeextend,
+ node = initializeextend,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local function initializesqueeze(tfmdata,value)
+ value = tonumber(value)
+ if not value then
+ value = 0
+ elseif value > 10 then
+ value = 10
+ elseif value < -10 then
+ value = -10
+ end
+ if trace then
+ report_squeeze("applying %0.3f",value)
+ end
+ tfmdata.parameters.squeezefactor = value
+end
+
+local specification = {
+ name = "squeeze",
+ description = "scale glyphs vertically",
+ initializers = {
+ base = initializesqueeze,
+ node = initializesqueeze,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local effects = {
+ inner = 0,
+ normal = 0,
+ outer = 1,
+ outline = 1,
+ both = 2,
+ hidden = 3,
+}
+
+local function initializeeffect(tfmdata,value)
+ local spec
+ if type(value) == "number" then
+ spec = { width = value }
+ else
+ spec = settings_to_hash(value)
+ end
+ local effect = spec.effect or "both"
+ local width = tonumber(spec.width) or 0
+ local mode = effects[effect]
+ if not mode then
+ report_effect("invalid effect %a",effect)
+ elseif width == 0 and mode == 0 then
+ report_effect("invalid width %a for effect %a",width,effect)
+ else
+ local parameters = tfmdata.parameters
+ local properties = tfmdata.properties
+ parameters.mode = mode
+ parameters.width = width * 1000
+ if is_boolean(spec.auto) == true then
+ local squeeze = 1 - width/20
+ local average = (1 - squeeze) * width * 100
+ spec.squeeze = squeeze
+ spec.extend = 1 + width/2
+ spec.wdelta = average
+ spec.hdelta = average/2
+ spec.ddelta = average/2
+ spec.vshift = average/2
+ end
+ local factor = tonumber(spec.factor) or 0
+ local hfactor = tonumber(spec.hfactor) or factor
+ local vfactor = tonumber(spec.vfactor) or factor
+ local delta = tonumber(spec.delta) or 1
+ local wdelta = tonumber(spec.wdelta) or delta
+ local hdelta = tonumber(spec.hdelta) or delta
+ local ddelta = tonumber(spec.ddelta) or hdelta
+ local vshift = tonumber(spec.vshift) or 0
+ local slant = spec.slant
+ local extend = spec.extend
+ local squeeze = spec.squeeze
+ if slant then
+ initializeslant(tfmdata,slant)
+ end
+ if extend then
+ initializeextend(tfmdata,extend)
+ end
+ if squeeze then
+ initializesqueeze(tfmdata,squeeze)
+ end
+ properties.effect = {
+ effect = effect,
+ width = width,
+ factor = factor,
+ hfactor = hfactor,
+ vfactor = vfactor,
+ wdelta = wdelta,
+ hdelta = hdelta,
+ ddelta = ddelta,
+ vshift = vshift,
+ slant = tfmdata.parameters.slantfactor,
+ extend = tfmdata.parameters.extendfactor,
+ squeeze = tfmdata.parameters.squeezefactor,
+ }
+ end
+end
+
+local rules = {
+ "RadicalRuleThickness",
+ "OverbarRuleThickness",
+ "FractionRuleThickness",
+ "UnderbarRuleThickness",
+}
+
+-- local commands = char.commands
+-- if commands then
+-- local command = commands[1]
+-- if command and command[1] == "right" then
+-- commands[1] = rightcommand[command[2]-snap]
+-- end
+-- end
+
+local function setmathparameters(tfmdata,characters,mathparameters,dx,dy,squeeze)
+ if delta ~= 0 then
+ for i=1,#rules do
+ local name = rules[i]
+ local value = mathparameters[name]
+ if value then
+ mathparameters[name] = (squeeze or 1) * (value + dx)
+ end
+ end
+ end
+end
+
+local function setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze,wdelta,hdelta,ddelta)
+
+ local function wdpatch(char)
+ if wsnap ~= 0 then
+ char.width = char.width + wdelta/2
+ end
+ end
+
+ local function htpatch(char)
+ if hsnap ~= 0 then
+ local height = char.height
+ if height then
+ char.height = char.height + 2 * dy
+ end
+ end
+ end
+
+ local character = characters[0x221A]
+
+ if character and character.next then
+-- print("base char",0x221A,table.sequenced(character))
+ local char = character
+ local next = character.next
+ wdpatch(char)
+ htpatch(char)
+ while next do
+ char = characters[next]
+ wdpatch(char)
+ htpatch(char)
+-- print("next char",next,table.sequenced(char))
+ next = char.next
+ end
+ if char then
+ local v = char.vert_variants
+ if v then
+ local top = v[#v]
+ if top then
+ local char = characters[top.glyph]
+-- print("top char",top.glyph,table.sequenced(char))
+ htpatch(char)
+ end
+ end
+ end
+ end
+end
+
+-- local show_effect = { "lua", function(f,c)
+-- report_effect("font id %i, char %C",f,c)
+-- inspect(fonts.hashes.characters[f][c])
+-- end }
+
+-- local show_effect = { "lua", "print('!')" }
+
+local function manipulateeffect(tfmdata)
+ local effect = tfmdata.properties.effect
+ if effect then
+ local characters = tfmdata.characters
+ local parameters = tfmdata.parameters
+ local mathparameters = tfmdata.mathparameters
+ local multiplier = effect.width * 100
+ local factor = parameters.factor
+ local hfactor = parameters.hfactor
+ local vfactor = parameters.vfactor
+ local wdelta = effect.wdelta * hfactor * multiplier
+ local hdelta = effect.hdelta * vfactor * multiplier
+ local ddelta = effect.ddelta * vfactor * multiplier
+ local vshift = effect.vshift * vfactor * multiplier
+ local squeeze = effect.squeeze
+ local hshift = wdelta / 2
+ local dx = multiplier * vfactor
+ local dy = vshift
+ local factor = (1 + effect.factor) * factor
+ local hfactor = (1 + effect.hfactor) * hfactor
+ local vfactor = (1 + effect.vfactor) * vfactor
+ local vshift = vshift ~= 0 and upcommand[vshift] or false
+ for unicode, character in next, characters do
+ local oldwidth = character.width
+ local oldheight = character.height
+ local olddepth = character.depth
+ if oldwidth and oldwidth > 0 then
+ character.width = oldwidth + wdelta
+ local commands = character.commands
+ local hshift = rightcommand[hshift]
+ if vshift then
+ if commands then
+ prependcommands ( commands,
+-- show_effect,
+ hshift,
+ vshift
+ )
+ else
+ character.commands = {
+-- show_effect,
+ hshift,
+ vshift,
+ charcommand[unicode]
+ }
+ end
+ else
+ if commands then
+ prependcommands ( commands,
+-- show_effect,
+ hshift
+ )
+ else
+ character.commands = {
+-- show_effect,
+ hshift,
+ charcommand[unicode]
+ }
+ end
+ end
+ end
+ if oldheight and oldheight > 0 then
+ character.height = oldheight + hdelta
+ end
+ if olddepth and olddepth > 0 then
+ character.depth = olddepth + ddelta
+ end
+ end
+ if mathparameters then
+ setmathparameters(tfmdata,characters,mathparameters,dx,dy,squeeze)
+ setmathcharacters(tfmdata,characters,mathparameters,dx,dy,squeeze,wdelta,hdelta,ddelta)
+ end
+ parameters.factor = factor
+ parameters.hfactor = hfactor
+ parameters.vfactor = vfactor
+ if trace then
+ report_effect("applying")
+ report_effect(" effect : %s", effect.effect)
+ report_effect(" width : %s => %s", effect.width, multiplier)
+ report_effect(" factor : %s => %s", effect.factor, factor )
+ report_effect(" hfactor : %s => %s", effect.hfactor,hfactor)
+ report_effect(" vfactor : %s => %s", effect.vfactor,vfactor)
+ report_effect(" wdelta : %s => %s", effect.wdelta, wdelta)
+ report_effect(" hdelta : %s => %s", effect.hdelta, hdelta)
+ report_effect(" ddelta : %s => %s", effect.ddelta, ddelta)
+ end
+ end
+end
+
+local specification = {
+ name = "effect",
+ description = "apply effects to glyphs",
+ initializers = {
+ base = initializeeffect,
+ node = initializeeffect,
+ },
+ manipulators = {
+ base = manipulateeffect,
+ node = manipulateeffect,
+ },
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local function initializeoutline(tfmdata,value)
+ value = tonumber(value)
+ if not value then
+ value = 0
+ else
+ value = tonumber(value) or 0
+ end
+ local parameters = tfmdata.parameters
+ local properties = tfmdata.properties
+ parameters.mode = effects.outline
+ parameters.width = value * 1000
+ properties.effect = {
+ effect = effect,
+ width = width,
+ }
+end
+
+local specification = {
+ name = "outline",
+ description = "outline glyphs",
+ initializers = {
+ base = initializeoutline,
+ node = initializeoutline,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
diff --git a/tex/context/base/mkiv/font-imp-italics.lua b/tex/context/base/mkiv/font-imp-italics.lua
new file mode 100644
index 000000000..83c785d38
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-italics.lua
@@ -0,0 +1,147 @@
+if not modules then modules = { } end modules ['font-imp-italics'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next = next
+
+local fonts = fonts
+local handlers = fonts.handlers
+local registerotffeature = handlers.otf.features.register
+local registerafmfeature = handlers.afm.features.register
+
+local function initialize(tfmdata,key,value)
+ for unicode, character in next, tfmdata.characters do
+ local olditalic = character.italic
+ if olditalic and olditalic ~= 0 then
+ character.width = character.width + olditalic
+ character.italic = 0
+ end
+ end
+end
+
+local specification = {
+ name = "italicwidths",
+ description = "add italic to width",
+ manipulators = {
+ base = initialize,
+ node = initialize, -- only makes sense for math
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local function initialize(tfmdata,value) -- hm, always value
+ if value then
+ -- 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 properties = tfmdata.properties
+ local factor = tonumber(value) or 1
+ properties.hasitalics = true
+ properties.autoitalicamount = factor * (parameters.uwidth or 40)/2
+ end
+ end
+end
+
+local specification = {
+ name = "itlc",
+ description = "italic correction",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+if context then
+
+ local function initialize(tfmdata,value) -- yes no delay
+ tfmdata.properties.textitalics = toboolean(value)
+ end
+
+ local specification = {
+ name = "textitalics",
+ description = "use alternative text italic correction",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+ }
+
+ registerotffeature(specification)
+ registerafmfeature(specification)
+
+end
+
+-- no longer used
+
+-- if context then
+--
+-- -- local function initializemathitalics(tfmdata,value) -- yes no delay
+-- -- tfmdata.properties.mathitalics = toboolean(value)
+-- -- end
+-- --
+-- -- local specification = {
+-- -- name = "mathitalics",
+-- -- description = "use alternative math italic correction",
+-- -- initializers = {
+-- -- base = initializemathitalics,
+-- -- node = initializemathitalics,
+-- -- }
+-- -- }
+-- --
+-- -- registerotffeature(specification)
+-- -- registerafmfeature(specification)
+--
+-- end
+
+-- -- also not used, only when testing
+
+if context then
+
+ local letter = characters.is_letter
+ local always = true
+
+ local function collapseitalics(tfmdata,key,value)
+ local threshold = value == true and 100 or tonumber(value)
+ if threshold and threshold > 0 then
+ if threshold > 100 then
+ threshold = 100
+ end
+ for unicode, data in next, tfmdata.characters do
+ if always or letter[unicode] or letter[data.unicode] then
+ local italic = data.italic
+ if italic and italic ~= 0 then
+ local width = data.width
+ if width and width ~= 0 then
+ local delta = threshold * italic / 100
+ data.width = width + delta
+ data.italic = italic - delta
+ end
+ end
+ end
+ end
+ end
+ end
+
+ local dimensions_specification = {
+ name = "collapseitalics",
+ description = "collapse italics",
+ manipulators = {
+ base = collapseitalics,
+ node = collapseitalics,
+ }
+ }
+
+ registerotffeature(dimensions_specification)
+ registerafmfeature(dimensions_specification)
+
+end
diff --git a/tex/context/base/mkiv/font-imp-ligatures.lua b/tex/context/base/mkiv/font-imp-ligatures.lua
new file mode 100644
index 000000000..091eb5d4b
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-ligatures.lua
@@ -0,0 +1,136 @@
+if not modules then modules = { } end modules ['font-imp-ligatures'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lpegmatch = lpeg.match
+local utfsplit = utf.split
+local settings_to_array = utilities.parsers.settings_to_array
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+local registerotffeature = otf.features.register
+local addotffeature = otf.addfeature
+
+-- This is a quick and dirty hack.
+
+local lookups = { }
+local protect = { }
+local revert = { }
+local zwjchar = 0x200C
+local zwj = { zwjchar }
+
+addotffeature {
+ name = "blockligatures",
+ type = "chainsubstitution",
+ nocheck = true, -- because there is no 0x200C in the font
+ prepend = true, -- make sure we do it early
+ future = true, -- avoid nilling due to no steps yet
+ lookups = {
+ {
+ type = "multiple",
+ data = lookups,
+ },
+ },
+ data = {
+ rules = protect,
+ }
+}
+
+addotffeature {
+ name = "blockligatures",
+ type = "chainsubstitution",
+ nocheck = true, -- because there is no 0x200C in the font
+ append = true, -- this is done late
+ overload = false, -- we don't want to overload the previous definition
+ lookups = {
+ {
+ type = "ligature",
+ data = lookups,
+ },
+ },
+ data = {
+ rules = revert,
+ }
+}
+
+registerotffeature {
+ name = 'blockligatures',
+ description = 'block certain ligatures',
+}
+
+local splitter = lpeg.splitat(":")
+
+local function blockligatures(str)
+
+ local t = settings_to_array(str)
+
+ for i=1,#t do
+ local ti = t[i]
+ local before, current, after = lpegmatch(splitter,ti)
+ if current and after then -- before is returned when no match
+ -- experimental joke
+ if before then
+ before = utfsplit(before)
+ for i=1,#before do
+ before[i] = { before[i] }
+ end
+ end
+ if current then
+ current = utfsplit(current)
+ end
+ if after then
+ after = utfsplit(after)
+ for i=1,#after do
+ after[i] = { after[i] }
+ end
+ end
+ else
+ before = nil
+ current = utfsplit(ti)
+ after = nil
+ end
+ if #current > 1 then
+ local one = current[1]
+ local two = current[2]
+ lookups[one] = { one, zwjchar }
+ local one = { one }
+ local two = { two }
+ local new = #protect + 1
+ protect[new] = {
+ before = before,
+ current = { one, two },
+ after = after,
+ lookups = { 1 }, -- not shared !
+ }
+ revert[new] = {
+ -- before = before,
+ current = { one, zwj },
+ -- after = { two, unpack(after) },
+ after = { two },
+ lookups = { 1 }, -- not shared !
+ }
+ end
+ end
+end
+
+-- blockligatures("\0\0")
+
+otf.helpers.blockligatures = blockligatures
+
+-- blockligatures("fi,ff")
+-- blockligatures("fl")
+-- blockligatures("u:fl:age")
+
+if context then
+
+ interfaces.implement {
+ name = "blockligatures",
+ arguments = "string",
+ actions = blockligatures,
+ }
+
+end
diff --git a/tex/context/base/mkiv/font-imp-math.lua b/tex/context/base/mkiv/font-imp-math.lua
new file mode 100644
index 000000000..d93ece405
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-math.lua
@@ -0,0 +1,81 @@
+if not modules then modules = { } end modules ['font-imp-math'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not context then return end
+
+local next, type, tonumber = next, type, tonumber
+
+local fonts = fonts
+local helpers = fonts.helpers
+local registerotffeature = fonts.handlers.otf.features.register
+
+local setmetatableindex = table.setmetatableindex
+
+-- requested for latex but not supported unless really needed in context:
+--
+-- registerotffeature {
+-- name = "ignoremathconstants",
+-- description = "ignore math constants table",
+-- initializers = {
+-- base = function(tfmdata,value)
+-- if value then
+-- tfmdata.mathparameters = nil
+-- end
+-- end
+-- }
+-- }
+
+-- tfmdata.properties.mathnolimitsmode = tonumber(value) or 0
+
+local splitter = lpeg.splitat(",",tonumber)
+local lpegmatch = lpeg.match
+
+local function initialize(tfmdata,value)
+ local mathparameters = tfmdata.mathparameters
+ if mathparameters then
+ local sup, sub
+ if type(value) == "string" then
+ sup, sub = lpegmatch(splitter,value)
+ if not sup then
+ sub, sup = 0, 0
+ elseif not sub then
+ sub, sup = sup, 0
+ end
+ elseif type(value) == "number" then
+ sup, sub = 0, value
+ end
+ if sup then
+ mathparameters.NoLimitSupFactor = sup
+ end
+ if sub then
+ mathparameters.NoLimitSubFactor = sub
+ end
+ end
+end
+
+registerotffeature {
+ name = "mathnolimitsmode",
+ description = "influence nolimits placement",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+local function initialize(tfmdata,value)
+ tfmdata.properties.nostackmath = value and true
+end
+
+registerotffeature {
+ name = "nostackmath",
+ description = "disable math stacking mechanism",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
diff --git a/tex/context/base/mkiv/font-imp-notused.lua b/tex/context/base/mkiv/font-imp-notused.lua
new file mode 100644
index 000000000..be36c9898
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-notused.lua
@@ -0,0 +1,168 @@
+if not modules then modules = { } end modules ['font-imp-notused'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not context then return end
+
+-- local next = next
+-- local utfbyte = utf.byte
+--
+-- local fonts = fonts
+--
+-- local handlers = fonts.handlers
+-- local otf = handlers.otf
+-- local afm = handlers.afm
+--
+-- local registerotffeature = otf.features.register
+-- local registerafmfeature = afm.features.register
+
+-- local function initialize(tfmdata)
+-- local resources = tfmdata.resources
+-- local gposfeatures = resources.features.gpos
+-- local characters = tfmdata.characters
+-- local descriptions = tfmdata.descriptions
+-- local sequences = resources.sequences
+-- local coverage = { }
+-- local units = tfmdata.shared.rawdata.metadata.units
+-- for k, v in next, characters do
+-- local w = descriptions[k].width
+-- local d = units - w
+-- coverage[k] = { -d/2, 0, units, 0 }
+-- end
+-- local f = { dflt = { dflt = true } }
+-- local s = #sequences + 1
+-- local t = {
+-- features = { fakemono = f },
+-- flags = { false, false, false, false },
+-- index = s,
+-- name = "p_s_" .. s,
+-- nofsteps = 1,
+-- order = { "fakemono" },
+-- skiphash = false,
+-- type = "gpos_single",
+-- steps = {
+-- {
+-- format = "single",
+-- coverage = coverage,
+-- }
+-- }
+-- }
+-- gposfeatures["fakemono"] = f
+-- sequences[s] = t
+-- end
+--
+-- registerotffeature {
+-- name = "fakemono",
+-- description = "fake monospaced",
+-- initializers = {
+-- node = initialize,
+-- },
+-- }
+
+-- -- for notosans but not general
+--
+-- local v_local = interfaces and interfaces.variables and interfaces.variables["local"] or "local"
+--
+-- local function initialize(tfmdata,key,value)
+-- local characters = tfmdata.characters
+-- local parameters = tfmdata.parameters
+-- local oldchar = 32
+-- local newchar = 32
+-- if value == "locl" or value == v_local then
+-- newchar = fonts.handlers.otf.getsubstitution(tfmdata,oldchar,"locl",true) or oldchar
+-- elseif value == true then
+-- -- use normal space
+-- elseif value then
+-- newchar = utfbyte(value)
+-- else
+-- return
+-- end
+-- local newchar = newchar and characters[newchar]
+-- local newspace = newchar and newchar.width
+-- if newspace > 0 then
+-- parameters.space = newspace
+-- parameters.space_stretch = newspace/2
+-- parameters.space_shrink = newspace/3
+-- parameters.extra_space = parameters.space_shrink
+-- end
+-- end
+--
+-- registerotffeature {
+-- name = 'space', -- true|false|locl|character
+-- description = 'space settings',
+-- manipulators = {
+-- base = initialize,
+-- node = initialize,
+-- }
+-- }
+
+-- -- historic stuff, move from font-ota (handled differently, typo-rep)
+--
+-- local delete_node = nodes.delete
+-- local fontdata = fonts.hashes.identifiers
+--
+-- local nodecodes = nodes.nodecodes
+-- local glyph_code = nodecodes.glyph
+--
+-- local strippables = allocate()
+-- fonts.strippables = strippables
+--
+-- strippables.joiners = table.tohash {
+-- 0x200C, -- zwnj
+-- 0x200D, -- zwj
+-- }
+--
+-- strippables.all = table.tohash {
+-- 0x000AD, 0x017B4, 0x017B5, 0x0200B, 0x0200C, 0x0200D, 0x0200E, 0x0200F, 0x0202A, 0x0202B,
+-- 0x0202C, 0x0202D, 0x0202E, 0x02060, 0x02061, 0x02062, 0x02063, 0x0206A, 0x0206B, 0x0206C,
+-- 0x0206D, 0x0206E, 0x0206F, 0x0FEFF, 0x1D173, 0x1D174, 0x1D175, 0x1D176, 0x1D177, 0x1D178,
+-- 0x1D179, 0x1D17A, 0xE0001, 0xE0020, 0xE0021, 0xE0022, 0xE0023, 0xE0024, 0xE0025, 0xE0026,
+-- 0xE0027, 0xE0028, 0xE0029, 0xE002A, 0xE002B, 0xE002C, 0xE002D, 0xE002E, 0xE002F, 0xE0030,
+-- 0xE0031, 0xE0032, 0xE0033, 0xE0034, 0xE0035, 0xE0036, 0xE0037, 0xE0038, 0xE0039, 0xE003A,
+-- 0xE003B, 0xE003C, 0xE003D, 0xE003E, 0xE003F, 0xE0040, 0xE0041, 0xE0042, 0xE0043, 0xE0044,
+-- 0xE0045, 0xE0046, 0xE0047, 0xE0048, 0xE0049, 0xE004A, 0xE004B, 0xE004C, 0xE004D, 0xE004E,
+-- 0xE004F, 0xE0050, 0xE0051, 0xE0052, 0xE0053, 0xE0054, 0xE0055, 0xE0056, 0xE0057, 0xE0058,
+-- 0xE0059, 0xE005A, 0xE005B, 0xE005C, 0xE005D, 0xE005E, 0xE005F, 0xE0060, 0xE0061, 0xE0062,
+-- 0xE0063, 0xE0064, 0xE0065, 0xE0066, 0xE0067, 0xE0068, 0xE0069, 0xE006A, 0xE006B, 0xE006C,
+-- 0xE006D, 0xE006E, 0xE006F, 0xE0070, 0xE0071, 0xE0072, 0xE0073, 0xE0074, 0xE0075, 0xE0076,
+-- 0xE0077, 0xE0078, 0xE0079, 0xE007A, 0xE007B, 0xE007C, 0xE007D, 0xE007E, 0xE007F,
+-- }
+--
+-- strippables[true] = strippables.joiners
+--
+-- local function processformatters(head,font)
+-- local subset = fontdata[font].shared.features.formatters
+-- local vector = subset and strippables[subset]
+-- if vector then
+-- local current, done = head, false
+-- while current do
+-- if current.id == glyph_code and current.subtype<256 and current.font == font then
+-- local char = current.char
+-- if vector[char] then
+-- head, current = delete_node(head,current)
+-- done = true
+-- else
+-- current = current.next
+-- end
+-- else
+-- current = current.next
+-- end
+-- end
+-- return head, done
+-- else
+-- return head, false
+-- end
+-- end
+--
+-- registerotffeature {
+-- name = "formatters",
+-- description = "hide formatting characters",
+-- methods = {
+-- base = processformatters,
+-- node = processformatters,
+-- }
+-- }
diff --git a/tex/context/base/mkiv/font-imp-properties.lua b/tex/context/base/mkiv/font-imp-properties.lua
new file mode 100644
index 000000000..5805235b7
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-properties.lua
@@ -0,0 +1,130 @@
+if not modules then modules = { } end modules ['font-imp-properties'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not context then return end
+
+local next, type, tonumber, select = next, type, tonumber, select
+local byte, find, formatters = string.byte, string.find, string.formatters
+local utfchar = utf.char
+local sortedhash, sortedkeys, sort = table.sortedhash, table.sortedkeys, table.sort
+local insert = table.insert
+
+local context = context
+local fonts = fonts
+local utilities = utilities
+
+local helpers = fonts.helpers
+
+local handlers = fonts.handlers
+local hashes = fonts.hashes
+local otf = handlers.otf
+local afm = handlers.afm
+
+local registerotffeature = otf.features.register
+local registerafmfeature = afm.features.register
+
+local fontdata = hashes.identifiers
+local fontproperties = hashes.properties
+
+local constructors = fonts.constructors
+local getprivate = constructors.getprivate
+
+local allocate = utilities.storage.allocate
+local family_font = node.family_font
+
+local setmetatableindex = table.setmetatableindex
+
+local implement = interfaces.implement
+
+do
+
+ local P, lpegpatterns, lpegmatch = lpeg.P, lpeg.patterns, lpeg.match
+
+ local amount, stretch, shrink, extra
+
+ local factor = lpegpatterns.unsigned
+ local space = lpegpatterns.space
+ local pattern = (
+ (factor / function(n) amount = tonumber(n) or amount end)
+ + (P("+") + P("plus" )) * space^0 * (factor / function(n) stretch = tonumber(n) or stretch end)
+ + (P("-") + P("minus")) * space^0 * (factor / function(n) shrink = tonumber(n) or shrink end)
+ + ( P("extra")) * space^0 * (factor / function(n) extra = tonumber(n) or extra end)
+ + space^1
+ )^1
+
+ local function initialize(tfmdata,key,value)
+ local characters = tfmdata.characters
+ local parameters = tfmdata.parameters
+ if type(value) == "string" then
+ local emwidth = parameters.quad
+ amount, stretch, shrink, extra = 0, 0, 0, false
+ lpegmatch(pattern,value)
+ if not extra then
+ if shrink ~= 0 then
+ extra = shrink
+ elseif stretch ~= 0 then
+ extra = stretch
+ else
+ extra = amount
+ end
+ end
+ parameters.space = amount * emwidth
+ parameters.space_stretch = stretch * emwidth
+ parameters.space_shrink = shrink * emwidth
+ parameters.extra_space = extra * emwidth
+ end
+ end
+
+ -- 1.1 + 1.2 - 1.3 minus 1.4 plus 1.1 extra 1.4 -- last one wins
+
+ registerotffeature {
+ name = "spacing",
+ description = "space settings",
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+ }
+
+end
+
+do
+
+ local function initialize(tfmdata,value)
+ local properties = tfmdata.properties
+ if properties then
+ properties.identity = value == "vertical" and "vertical" or "horizontal"
+ end
+ end
+
+ registerotffeature {
+ name = "identity",
+ description = "set font identity",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+ }
+
+ local function initialize(tfmdata,value)
+ local properties = tfmdata.properties
+ if properties then
+ properties.writingmode = value == "vertical" and "vertical" or "horizontal"
+ end
+ end
+
+ registerotffeature {
+ name = "writingmode",
+ description = "set font direction",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+ }
+
+end
diff --git a/tex/context/base/mkiv/font-imp-quality.lua b/tex/context/base/mkiv/font-imp-quality.lua
new file mode 100644
index 000000000..01f0afe63
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-quality.lua
@@ -0,0 +1,527 @@
+if not modules then modules = { } end modules ['font-imp-quality'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not context then return end
+
+local next, type, tonumber = next, type, tonumber
+local byte = string.byte
+local insert = table.insert
+
+local fonts = fonts
+local utilities = utilities
+
+local handlers = fonts.handlers
+local otf = handlers.otf
+local afm = handlers.afm
+local registerotffeature = otf.features.register
+local registerafmfeature = afm.features.register
+
+local allocate = utilities.storage.allocate
+local getparameters = utilities.parsers.getparameters
+
+local implement = interfaces and interfaces.implement
+
+local trace_protrusion = false trackers.register("fonts.protrusion", function(v) trace_protrusion = v end)
+local trace_expansion = false trackers.register("fonts.expansion", function(v) trace_expansion = v end)
+
+local report_expansions = logs.reporter("fonts","expansions")
+local report_protrusions = logs.reporter("fonts","protrusions")
+
+-- -- -- -- -- --
+-- shared
+-- -- -- -- -- --
+
+local function get_class_and_vector(tfmdata,value,where) -- "expansions"
+ local g_where = tfmdata.goodies and tfmdata.goodies[where]
+ local f_where = fonts[where]
+ local g_classes = g_where and g_where.classes
+ local f_classes = f_where and f_where.classes
+ local class = (g_classes and g_classes[value]) or (f_classes and f_classes[value])
+ if class then
+ local class_vector = class.vector
+ local g_vectors = g_where and g_where.vectors
+ local f_vectors = f_where and f_where.vectors
+ local vector = (g_vectors and g_vectors[class_vector]) or (f_vectors and f_vectors[class_vector])
+ return class, vector
+ end
+end
+
+-- -- -- -- -- --
+-- expansion (hz)
+-- -- -- -- -- --
+
+local expansions = fonts.expansions or allocate()
+
+fonts.expansions = expansions
+
+local classes = expansions.classes or allocate()
+local vectors = expansions.vectors or allocate()
+
+expansions.classes = classes
+expansions.vectors = vectors
+
+-- beware, pdftex itself uses percentages * 10
+--
+-- todo: get rid of byte() here
+
+classes.preset = { stretch = 2, shrink = 2, step = .5, factor = 1 }
+
+classes['quality'] = {
+ stretch = 2, shrink = 2, step = .5, vector = 'default', factor = 1
+}
+
+vectors['default'] = {
+ [byte('A')] = 0.5, [byte('B')] = 0.7, [byte('C')] = 0.7, [byte('D')] = 0.5, [byte('E')] = 0.7,
+ [byte('F')] = 0.7, [byte('G')] = 0.5, [byte('H')] = 0.7, [byte('K')] = 0.7, [byte('M')] = 0.7,
+ [byte('N')] = 0.7, [byte('O')] = 0.5, [byte('P')] = 0.7, [byte('Q')] = 0.5, [byte('R')] = 0.7,
+ [byte('S')] = 0.7, [byte('U')] = 0.7, [byte('W')] = 0.7, [byte('Z')] = 0.7,
+ [byte('a')] = 0.7, [byte('b')] = 0.7, [byte('c')] = 0.7, [byte('d')] = 0.7, [byte('e')] = 0.7,
+ [byte('g')] = 0.7, [byte('h')] = 0.7, [byte('k')] = 0.7, [byte('m')] = 0.7, [byte('n')] = 0.7,
+ [byte('o')] = 0.7, [byte('p')] = 0.7, [byte('q')] = 0.7, [byte('s')] = 0.7, [byte('u')] = 0.7,
+ [byte('w')] = 0.7, [byte('z')] = 0.7,
+ [byte('2')] = 0.7, [byte('3')] = 0.7, [byte('6')] = 0.7, [byte('8')] = 0.7, [byte('9')] = 0.7,
+}
+
+vectors['quality'] = vectors['default'] -- metatable ?
+
+local function initialize(tfmdata,value)
+ if value then
+ local class, vector = get_class_and_vector(tfmdata,value,"expansions")
+ if class then
+ if vector then
+ local stretch = class.stretch or 0
+ local shrink = class.shrink or 0
+ local step = class.step or 0
+ local factor = class.factor or 1
+ if trace_expansion then
+ report_expansions("setting class %a, vector %a, factor %a, stretch %a, shrink %a, step %a",
+ value,class.vector,factor,stretch,shrink,step)
+ end
+ tfmdata.parameters.expansion = {
+ stretch = 10 * stretch,
+ shrink = 10 * shrink,
+ step = 10 * step,
+ factor = factor,
+ }
+ local data = characters and characters.data
+ for i, chr in next, tfmdata.characters do
+ local v = vector[i]
+ if data and not v then -- we could move the data test outside (needed for plain)
+ local d = data[i]
+ if d then
+ local s = d.shcode
+ if not s then
+ -- sorry
+ elseif type(s) == "table" then
+ v = ((vector[s[1]] or 0) + (vector[s[#s]] or 0)) / 2
+ else
+ v = vector[s] or 0
+ end
+ end
+ end
+ if v and v ~= 0 then
+ chr.expansion_factor = v*factor
+ else -- can be option
+ chr.expansion_factor = factor
+ end
+ end
+ elseif trace_expansion then
+ report_expansions("unknown vector %a in class %a",class.vector,value)
+ end
+ elseif trace_expansion then
+ report_expansions("unknown class %a",value)
+ end
+ end
+end
+
+local specification = {
+ name = "expansion",
+ description = "apply hz optimization",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+fonts.goodies.register("expansions", function(...) return fonts.goodies.report("expansions", trace_expansion, ...) end)
+
+if context then
+
+ implement {
+ name = "setupfontexpansion",
+ arguments = "2 strings",
+ actions = function(class,settings) getparameters(classes,class,'preset',settings) end
+ }
+
+end
+
+-- -- -- -- -- --
+-- protrusion
+-- -- -- -- -- --
+
+fonts.protrusions = allocate()
+local protrusions = fonts.protrusions
+
+protrusions.classes = allocate()
+protrusions.vectors = allocate()
+
+local classes = protrusions.classes
+local vectors = protrusions.vectors
+
+-- the values need to be revisioned
+
+classes.preset = { factor = 1, left = 1, right = 1 }
+
+classes['pure'] = {
+ vector = 'pure', factor = 1
+}
+classes['punctuation'] = {
+ vector = 'punctuation', factor = 1
+}
+classes['alpha'] = {
+ vector = 'alpha', factor = 1
+}
+classes['quality'] = {
+ vector = 'quality', factor = 1
+}
+
+vectors['pure'] = {
+
+ [0x002C] = { 0, 1 }, -- comma
+ [0x002E] = { 0, 1 }, -- period
+ [0x003A] = { 0, 1 }, -- colon
+ [0x003B] = { 0, 1 }, -- semicolon
+ [0x002D] = { 0, 1 }, -- hyphen
+ [0x00AD] = { 0, 1 }, -- also hyphen
+ [0x2013] = { 0, 0.50 }, -- endash
+ [0x2014] = { 0, 0.33 }, -- emdash
+ [0x3001] = { 0, 1 }, -- ideographic comma 、
+ [0x3002] = { 0, 1 }, -- ideographic full stop 。
+ [0x060C] = { 0, 1 }, -- arabic comma ،
+ [0x061B] = { 0, 1 }, -- arabic semicolon ؛
+ [0x06D4] = { 0, 1 }, -- arabic full stop ۔
+
+}
+
+vectors['punctuation'] = {
+
+ [0x003F] = { 0, 0.20 }, -- ?
+ [0x00BF] = { 0.20, 0 }, -- ¿
+ [0x0021] = { 0, 0.20 }, -- !
+ [0x00A1] = { 0.20, 0, }, -- ¡
+ [0x0028] = { 0.05, 0 }, -- (
+ [0x0029] = { 0, 0.05 }, -- )
+ [0x005B] = { 0.05, 0 }, -- [
+ [0x005D] = { 0, 0.05 }, -- ]
+ [0x002C] = { 0, 0.70 }, -- comma
+ [0x002E] = { 0, 0.70 }, -- period
+ [0x003A] = { 0, 0.50 }, -- colon
+ [0x003B] = { 0, 0.50 }, -- semicolon
+ [0x002D] = { 0, 0.70 }, -- hyphen
+ [0x00AD] = { 0, 0.70 }, -- also hyphen
+ [0x2013] = { 0, 0.30 }, -- endash
+ [0x2014] = { 0, 0.20 }, -- emdash
+ [0x060C] = { 0, 0.70 }, -- arabic comma
+ [0x061B] = { 0, 0.50 }, -- arabic semicolon
+ [0x06D4] = { 0, 0.70 }, -- arabic full stop
+ [0x061F] = { 0, 0.20 }, -- ؟
+
+ -- todo: left and right quotes: .5 double, .7 single
+
+ [0x2039] = { 0.70, 0.70 }, -- left single guillemet ‹
+ [0x203A] = { 0.70, 0.70 }, -- right single guillemet ›
+ [0x00AB] = { 0.50, 0.50 }, -- left guillemet «
+ [0x00BB] = { 0.50, 0.50 }, -- right guillemet »
+
+ [0x2018] = { 0.70, 0.70 }, -- left single quotation mark ‘
+ [0x2019] = { 0, 0.70 }, -- right single quotation mark ’
+ [0x201A] = { 0.70, 0 }, -- single low-9 quotation mark ,
+ [0x201B] = { 0.70, 0 }, -- single high-reversed-9 quotation mark ‛
+ [0x201C] = { 0.50, 0.50 }, -- left double quotation mark “
+ [0x201D] = { 0, 0.50 }, -- right double quotation mark ”
+ [0x201E] = { 0.50, 0 }, -- double low-9 quotation mark „
+ [0x201F] = { 0.50, 0 }, -- double high-reversed-9 quotation mark ‟
+
+}
+
+vectors['alpha'] = {
+
+ [byte("A")] = { .05, .05 },
+ [byte("F")] = { 0, .05 },
+ [byte("J")] = { .05, 0 },
+ [byte("K")] = { 0, .05 },
+ [byte("L")] = { 0, .05 },
+ [byte("T")] = { .05, .05 },
+ [byte("V")] = { .05, .05 },
+ [byte("W")] = { .05, .05 },
+ [byte("X")] = { .05, .05 },
+ [byte("Y")] = { .05, .05 },
+
+ [byte("k")] = { 0, .05 },
+ [byte("r")] = { 0, .05 },
+ [byte("t")] = { 0, .05 },
+ [byte("v")] = { .05, .05 },
+ [byte("w")] = { .05, .05 },
+ [byte("x")] = { .05, .05 },
+ [byte("y")] = { .05, .05 },
+
+}
+
+vectors['quality'] = table.merged(
+ vectors['punctuation'],
+ vectors['alpha']
+)
+
+-- As this is experimental code, users should not depend on it. The implications are still
+-- discussed on the ConTeXt Dev List and we're not sure yet what exactly the spec is (the
+-- next code is tested with a gyre font patched by / fea file made by Khaled Hosny). The
+-- double trick should not be needed it proper hanging punctuation is used in which case
+-- values < 1 can be used.
+--
+-- preferred (in context, usine vectors):
+--
+-- \definefontfeature[whatever][default][mode=node,protrusion=quality]
+--
+-- using lfbd and rtbd, with possibibility to enable only one side :
+--
+-- \definefontfeature[whocares][default][mode=node,protrusion=yes, opbd=yes,script=latn]
+-- \definefontfeature[whocares][default][mode=node,protrusion=right,opbd=yes,script=latn]
+--
+-- idem, using multiplier
+--
+-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn]
+-- \definefontfeature[whocares][default][mode=node,protrusion=double,opbd=yes,script=latn]
+--
+-- idem, using named feature file (less frozen):
+--
+-- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea]
+
+classes['double'] = { -- for testing opbd
+ factor = 2, left = 1, right = 1,
+}
+
+local function map_opbd_onto_protrusion(tfmdata,value,opbd)
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local properties = tfmdata.properties
+ local parameters = tfmdata.parameters
+ local resources = tfmdata.resources
+ local rawdata = tfmdata.shared.rawdata
+ local lookuphash = rawdata.lookuphash
+ local lookuptags = resources.lookuptags
+ local script = properties.script
+ local language = properties.language
+ local units = parameters.units
+ local done, factor, left, right = false, 1, 1, 1
+ local class = classes[value]
+ if class then
+ factor = class.factor or 1
+ left = class.left or 1
+ right = class.right or 1
+ else
+ factor = tonumber(value) or 1
+ end
+ local lfactor = left * factor
+ local rfactor = right * factor
+ if trace_protrusion then
+ report_protrusions("left factor %0.3F, right factor %0.3F",lfactor,rfactor)
+ end
+ tfmdata.parameters.protrusion = {
+ factor = factor,
+ left = left,
+ right = right,
+ }
+ if opbd ~= "right" then
+ local validlookups, lookuplist = otf.collectlookups(rawdata,"lfbd",script,language)
+ if validlookups then
+ for i=1,#lookuplist do
+ local lookup = lookuplist[i]
+ local steps = lookup.steps
+ if steps then
+ if trace_protrusion then
+ report_protrusions("setting left using lfbd")
+ end
+ for i=1,#steps do
+ local step = steps[i]
+ local coverage = step.coverage
+ if coverage then
+ for k, v in next, coverage do
+ if v == true then
+ -- zero
+ else
+ local w = descriptions[k].width
+ local d = - v[1]
+ if w == 0 or d == 0 then
+ -- ignored
+ else
+ local p = lfactor * d/units
+ characters[k].left_protruding = p
+ if trace_protrusion then
+ report_protrusions("lfbd -> %0.3F %C",p,k)
+ end
+ end
+ end
+ end
+ end
+ end
+ done = true
+ end
+ end
+ end
+ end
+ if opbd ~= "left" then
+ local validlookups, lookuplist = otf.collectlookups(rawdata,"rtbd",script,language)
+ if validlookups then
+ for i=1,#lookuplist do
+ local lookup = lookuplist[i]
+ local steps = lookup.steps
+ if steps then
+ if trace_protrusion then
+ report_protrusions("setting right using rtbd")
+ end
+ for i=1,#steps do
+ local step = steps[i]
+ local coverage = step.coverage
+ if coverage then
+ for k, v in next, coverage do
+ if v == true then
+ -- zero
+ else
+ local w = descriptions[k].width
+ local d = - v[3]
+ if w == 0 or d == 0 then
+ -- ignored
+ else
+ local p = rfactor * d/units
+ characters[k].right_protruding = p
+ if trace_protrusion then
+ report_protrusions("rtbd -> %0.3F %C",p,k)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ done = true
+ end
+ end
+ end
+end
+
+-- The opbd test is just there because it was discussed on the context development list. However,
+-- the mentioned fxlbi.otf font only has some kerns for digits. So, consider this feature not supported
+-- till we have a proper test font.
+
+local function initialize(tfmdata,value)
+ if value then
+ local opbd = tfmdata.shared.features.opbd
+ if opbd then
+ -- possible values: left right both yes no (experimental)
+ map_opbd_onto_protrusion(tfmdata,value,opbd)
+ else
+ local class, vector = get_class_and_vector(tfmdata,value,"protrusions")
+ if class then
+ if vector then
+ local factor = class.factor or 1
+ local left = class.left or 1
+ local right = class.right or 1
+ if trace_protrusion then
+ report_protrusions("setting class %a, vector %a, factor %a, left %a, right %a",
+ value,class.vector,factor,left,right)
+ end
+ local data = characters.data
+ local emwidth = tfmdata.parameters.quad
+ local lfactor = left * factor
+ local rfactor = right * factor
+ if trace_protrusion then
+ report_protrusions("left factor %0.3F, right factor %0.3F",lfactor,rfactor)
+ end
+ tfmdata.parameters.protrusion = {
+ factor = factor,
+ left = left,
+ right = right,
+ }
+ for i, chr in next, tfmdata.characters do
+ local v = vector[i]
+ local pl = nil
+ local pr = nil
+ if v then
+ pl = v[1]
+ pr = v[2]
+ else
+ local d = data[i]
+ if d then
+ local s = d.shcode
+ if not s then
+ -- sorry
+ elseif type(s) == "table" then
+ local vl = vector[s[1]]
+ local vr = vector[s[#s]]
+ if vl then pl = vl[1] end
+ if vr then pr = vr[2] end
+ else
+ v = vector[s]
+ if v then
+ pl = v[1]
+ pr = v[2]
+ end
+ end
+ end
+ end
+ if pl and pl ~= 0 then
+ local p = pl * lfactor
+ chr.left_protruding = p
+ if trace_protrusion then
+ report_protrusions("left -> %0.3F %C ",p,i)
+ end
+ end
+ if pr and pr ~= 0 then
+ local p = pr * rfactor
+ chr.right_protruding = p
+ if trace_protrusion then
+ report_protrusions("right -> %0.3F %C",p,i)
+ end
+ end
+ end
+ elseif trace_protrusion then
+ report_protrusions("unknown vector %a in class %a",class.vector,value)
+ end
+ elseif trace_protrusion then
+ report_protrusions("unknown class %a",value)
+ end
+ end
+ end
+end
+
+local specification = {
+ name = "protrusion",
+ description = "l/r margin character protrusion",
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+fonts.goodies.register("protrusions", function(...) return fonts.goodies.report("protrusions", trace_protrusion, ...) end)
+
+if context then
+
+ implement {
+ name = "setupfontprotrusion",
+ arguments = "2 strings",
+ actions = function(class,settings) getparameters(classes,class,'preset',settings) end
+ }
+
+end
diff --git a/tex/context/base/mkiv/font-imp-reorder.lua b/tex/context/base/mkiv/font-imp-reorder.lua
new file mode 100644
index 000000000..b2dec781c
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-reorder.lua
@@ -0,0 +1,174 @@
+if not modules then modules = { } end modules ['font-imp-reorder'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not context then return end
+
+local next = next
+local find = string.find
+local sortedhash, sortedkeys, sort = table.sortedhash, table.sortedkeys, table.sort
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+local registerotffeature = otf.features.register
+
+-- This is a rather special test-only feature that I added for the sake of testing
+-- Idris's husayni. We wanted to know if uniscribe obeys the order of lookups in a
+-- font, in spite of what the description of handling arabic suggests. And indeed,
+-- mixed-in lookups of other features (like all these ss* in husayni) are handled
+-- the same in context as in uniscribe. If one sets reorderlookups=arab then we sort
+-- according to the "assumed" order so e.g. the ss* move to after the standard
+-- features. The observed difference in rendering is an indication that uniscribe is
+-- quite faithful to the font (while e.g. tests with the hb plugin demonstrate some
+-- interference, apart from some hard coded init etc expectations). Anyway, it means
+-- that we're okay with the (generic) node processor. A pitfall is that in context
+-- we can actually control more, so we can trigger an analyze pass with e.g.
+-- dflt/dflt while the libraries depend on the script settings for that. Uniscribe
+-- probably also parses the string and when seeing arabic will follow a different
+-- code path, although it seems to treat all features equal.
+
+local trace_reorder = trackers.register("fonts.reorderlookups",function(v) trace_reorder = v end)
+local report_reorder = logs.reporter("fonts","reorder")
+
+local vectors = { }
+
+vectors.arab = {
+ gsub = {
+ ccmp = 1,
+ isol = 2,
+ fina = 3,
+ medi = 4,
+ init = 5,
+ rlig = 6,
+ rclt = 7,
+ calt = 8,
+ liga = 9,
+ dlig = 10,
+ cswh = 11,
+ mset = 12,
+ },
+ gpos = {
+ curs = 1,
+ kern = 2,
+ mark = 3,
+ mkmk = 4,
+ },
+}
+
+local function compare(a,b)
+ local what_a = a.what
+ local what_b = b.what
+ if what_a ~= what_b then
+ return a.index < b.index
+ end
+ local when_a = a.when
+ local when_b = b.when
+ if when_a == when_b then
+ return a.index < b.index
+ else
+ return when_a < when_b
+ end
+end
+
+function otf.reorderlookups(tfmdata,vector)
+ local order = vectors[vector]
+ if not order then
+ return
+ end
+ local oldsequences = tfmdata.resources.sequences
+ if oldsequences then
+ local sequences = { }
+ for i=1,#oldsequences do
+ sequences[i] = oldsequences[i]
+ end
+ for i=1,#sequences do
+ local s = sequences[i]
+ local features = s.features
+ local kind = s.type
+ local index = s.index
+ if features then
+ local when
+ local what
+ for feature in sortedhash(features) do
+ if not what then
+ what = find(kind,"^gsub") and "gsub" or "gpos"
+ end
+ local newwhen = order[what][feature]
+ if not newwhen then
+ -- skip
+ elseif not when then
+ when = newwhen
+ elseif newwhen < when then
+ when = newwhen
+ end
+ end
+ s.ondex = s.index
+ s.index = i
+ s.what = what == "gsub" and 1 or 2
+ s.when = when or 99
+ else
+ s.ondex = s.index
+ s.index = i
+ s.what = 1
+ s.when = 99
+ end
+ end
+ sort(sequences,compare)
+ local swapped = 0
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local features = sequence.features
+ if features then
+ local index = sequence.index
+ if index ~= i then
+ swapped = swapped + 1
+ end
+ if trace_reorder then
+ if swapped == 1 then
+ report_reorder()
+ report_reorder("start swapping lookups in font %!font:name!",tfmdata)
+ report_reorder()
+ report_reorder("gsub order: % t",table.swapped(order.gsub))
+ report_reorder("gpos order: % t",table.swapped(order.gpos))
+ report_reorder()
+ end
+ report_reorder("%03i : lookup %03i, type %s, sorted %2i, moved %s, % t",
+ i,index,sequence.what == 1 and "gsub" or "gpos",sequence.when or 99,
+ (index > i and "-") or (index < i and "+") or "=",sortedkeys(features))
+ end
+ end
+ sequence.what = nil
+ sequence.when = nil
+ sequence.index = sequence.ondex
+ end
+ if swapped > 0 then
+ if trace_reorder then
+ report_reorder()
+ report_reorder("stop swapping lookups, %i lookups swapped",swapped)
+ report_reorder()
+ end
+ tfmdata.shared.reorderedsequences = sequences
+ end
+ end
+end
+
+-- maybe delay till ra is filled
+
+local function initialize(tfmdata,key,value)
+ if value then
+ otf.reorderlookups(tfmdata,value)
+ end
+end
+
+registerotffeature {
+ name = "reorderlookups",
+ description = "reorder lookups",
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
diff --git a/tex/context/base/mkiv/font-imp-tex.lua b/tex/context/base/mkiv/font-imp-tex.lua
new file mode 100644
index 000000000..b4b9a7b69
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-tex.lua
@@ -0,0 +1,144 @@
+if not modules then modules = { } end modules ['font-imp-tex'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next = next
+
+local fonts = fonts
+local otf = fonts.handlers.otf
+local registerotffeature = otf.features.register
+local addotffeature = otf.addfeature
+
+-- tlig (we need numbers for some fonts so ...)
+
+local specification = {
+ type = "ligature",
+ order = { "tlig" },
+ prepend = true,
+ data = {
+ -- endash = "hyphen hyphen",
+ -- emdash = "hyphen hyphen hyphen",
+ [0x2013] = { 0x002D, 0x002D },
+ [0x2014] = { 0x002D, 0x002D, 0x002D },
+ -- quotedblleft = "quoteleft quoteleft",
+ -- quotedblright = "quoteright quoteright",
+ -- quotedblleft = "grave grave",
+ -- quotedblright = "quotesingle quotesingle",
+ -- quotedblbase = "comma comma",
+ },
+}
+
+addotffeature("tlig",specification)
+
+registerotffeature {
+ -- this makes it a known feature (in tables)
+ name = "tlig",
+ description = "tex ligatures",
+}
+
+-- trep
+
+local specification = {
+ type = "substitution",
+ order = { "trep" },
+ prepend = true,
+ data = {
+ -- [0x0022] = 0x201D,
+ [0x0027] = 0x2019,
+ -- [0x0060] = 0x2018,
+ },
+}
+
+addotffeature("trep",specification)
+
+registerotffeature {
+ -- this makes it a known feature (in tables)
+ name = "trep",
+ description = "tex replacements",
+}
+
+-- some day this will be moved to font-imp-scripts.lua
+
+-- anum
+
+local anum_arabic = {
+ [0x0030] = 0x0660,
+ [0x0031] = 0x0661,
+ [0x0032] = 0x0662,
+ [0x0033] = 0x0663,
+ [0x0034] = 0x0664,
+ [0x0035] = 0x0665,
+ [0x0036] = 0x0666,
+ [0x0037] = 0x0667,
+ [0x0038] = 0x0668,
+ [0x0039] = 0x0669,
+}
+
+local anum_persian = {
+ [0x0030] = 0x06F0,
+ [0x0031] = 0x06F1,
+ [0x0032] = 0x06F2,
+ [0x0033] = 0x06F3,
+ [0x0034] = 0x06F4,
+ [0x0035] = 0x06F5,
+ [0x0036] = 0x06F6,
+ [0x0037] = 0x06F7,
+ [0x0038] = 0x06F8,
+ [0x0039] = 0x06F9,
+}
+
+local function valid(data)
+ local features = data.resources.features
+ if features then
+ for k, v in next, features do
+ for k, v in next, v do
+ if v.arab then
+ return true
+ end
+ end
+ end
+ end
+end
+
+local specification = {
+ {
+ type = "substitution",
+ features = { arab = { urd = true, dflt = true } },
+ order = { "anum" },
+ data = anum_arabic,
+ valid = valid,
+ },
+ {
+ type = "substitution",
+ features = { arab = { urd = true } },
+ order = { "anum" },
+ data = anum_persian,
+ valid = valid,
+ },
+}
+
+addotffeature("anum",specification)
+
+registerotffeature {
+ -- this makes it a known feature (in tables)
+ name = "anum",
+ description = "arabic digits",
+}
+
+-- -- example:
+--
+-- fonts.handlers.otf.addfeature {
+-- name = "hangulfix",
+-- type = "substitution",
+-- features = { ["hang"] = { ["*"] = true } },
+-- data = {
+-- [0x1160] = 0x119E,
+-- },
+-- order = { "hangulfix" },
+-- flags = { },
+-- prepend = true,
+-- })
diff --git a/tex/context/base/mkiv/font-imp-tracing.lua b/tex/context/base/mkiv/font-imp-tracing.lua
new file mode 100644
index 000000000..6ce445143
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-tracing.lua
@@ -0,0 +1,281 @@
+if not modules then modules = { } end modules ['font-imp-tracing'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not context then return end
+
+local next, type = next, type
+local concat = table.concat
+local formatters = string.formatters
+
+local fonts = fonts
+
+local handlers = fonts.handlers
+local registerotffeature = handlers.otf.features.register
+local registerafmfeature = handlers.afm.features.register
+
+local settings_to_array = utilities.parsers.settings_to_array
+local setmetatableindex = table.setmetatableindex
+
+local helpers = fonts.helpers
+local appendcommandtable = helpers.appendcommandtable
+local prependcommands = helpers.prependcommands
+local charcommand = helpers.commands.char
+
+local variables = interfaces.variables
+
+local v_background = variables.background
+local v_frame = variables.frame
+local v_empty = variables.empty
+local v_none = variables.none
+
+-- for zhichu chen (see mailing list archive): we might add a few more variants
+-- in due time
+--
+-- \definefontfeature[boxed][default][boundingbox=yes] % paleblue
+--
+-- maybe:
+--
+-- \definecolor[DummyColor][s=.75,t=.5,a=1] {\DummyColor test} \nopdfcompression
+--
+-- local gray = { "pdf", "origin", "/Tr1 gs .75 g" }
+-- local black = { "pdf", "origin", "/Tr0 gs 0 g" }
+
+-- boundingbox={yes|background|frame|empty|<color>}
+
+local bp = number.dimenfactors.bp
+local r = 16384 * bp -- 65536 // 4
+local f_1 = formatters["%.6F w 0 %.6F %.6F %.6F re f"]
+local f_2 = formatters["[] 0 d 0 J %.6F w %.6F %.6F %.6F %.6F re S"]
+
+-- change this into w h d instead of h d w
+
+local backcache = setmetatableindex(function(t,h)
+ local h = h * bp
+ local v = setmetatableindex(function(t,d)
+ local d = d * bp
+ local v = setmetatableindex(function(t,w)
+ local v = { "pdf", "origin", f_1(r,-d,w*bp,h+d) }
+ t[w] = v
+ return v
+ end)
+ t[d] = v
+ return v
+ end)
+ t[h] = v
+ return v
+end)
+
+local forecache = setmetatableindex(function(t,h)
+ local h = h * bp
+ local v = setmetatableindex(function(t,d)
+ local d = d * bp
+ local v = setmetatableindex(function(t,w)
+ -- the frame goes through the boundingbox
+ local v = { "pdf", "origin", f_2(r,r/2,-d+r/2,w*bp-r,h+d-r) }
+ t[w] = v
+ return v
+ end)
+ t[d] = v
+ return v
+ end)
+ t[h] = v
+ return v
+end)
+
+local startcolor = nil
+local stopcolor = nil
+
+local function initialize(tfmdata,key,value)
+ if value then
+ if not backcolors then
+ local vfspecials = backends.pdf.tables.vfspecials
+ startcolor = vfspecials.startcolor
+ stopcolor = vfspecials.stopcolor
+ end
+ local characters = tfmdata.characters
+ local rulecache = backcache
+ local showchar = true
+ local color = "palegray"
+ if type(value) == "string" then
+ value = settings_to_array(value)
+ for i=1,#value do
+ local v = value[i]
+ if v == v_frame then
+ rulecache = forecache
+ elseif v == v_background then
+ rulecache = backcache
+ elseif v == v_empty then
+ showchar = false
+ elseif v == v_none then
+ color = nil
+ else
+ color = v
+ end
+ end
+ end
+ local gray = color and startcolor(color) or nil
+ local black = gray and stopcolor or nil
+ for unicode, character in next, characters do
+ local width = character.width or 0
+ local height = character.height or 0
+ local depth = character.depth or 0
+ local rule = rulecache[height][depth][width]
+ if showchar then
+ local commands = character.commands
+ if commands then
+ if gray then
+ character.commands = prependcommands (
+ commands, gray, rule, black
+ )
+ else
+ character.commands = prependcommands (
+ commands, rule
+ )
+ end
+ else
+ local char = charcommand[unicode]
+ if gray then
+ character.commands = {
+ gray, rule, black, char
+ }
+ else
+ character.commands = {
+ rule, char
+ }
+ end
+ end
+ else
+ if gray then
+ character.commands = {
+ gray, rule, black
+ }
+ else
+ character.commands = {
+ rule
+ }
+ end
+ end
+ end
+ end
+end
+
+local specification = {
+ name = "boundingbox",
+ description = "show boundingbox",
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
+
+local f_m = formatters["%F %F m"]
+local f_l = formatters["%F %F l"]
+local f_b = formatters["[] 0 d 0 J %.6F w"]
+local f_e = formatters["s"]
+
+local function ladder(list,docolor,nocolor,lst,offset,sign,default)
+ local l = lst[1]
+ local x1 = bp * (offset + l.kern) * sign
+ local y1 = bp * l.height
+ local t = { f_b(r,r/2), f_m(x1,y1) }
+ local n = 2
+ local m = #lst
+ if default > 0 then
+ default = default * bp + r
+ else
+ default = default * bp - r
+ end
+ if m == 1 then
+ n = n + 1 t[n] = f_l(x1,default)
+ else
+ for i=1,m do
+ local l = lst[i]
+ local x2 = bp * (offset + l.kern) * sign
+ local y2 = bp * l.height
+ if i > 1 and y2 == 0 then
+ y2 = default
+ end
+ n = n + 1 t[n] = f_l(x2,y1)
+ n = n + 1 t[n] = f_l(x2,y2)
+ x1, y1 = x2, y2
+ end
+ end
+ n = n + 1 t[n] = f_e()
+ list[#list+1] = docolor
+ list[#list+1] = { "pdf", "origin", concat(t," ") }
+ list[#list+1] = nocolor
+end
+
+local function initialize(tfmdata,key,value)
+ if value then
+ if not backcolors then
+ local vfspecials = backends.pdf.tables.vfspecials
+ startcolor = vfspecials.startcolor
+ stopcolor = vfspecials.stopcolor
+ end
+ local characters = tfmdata.characters
+ local brcolor = startcolor("darkred")
+ local trcolor = startcolor("darkgreen")
+ local blcolor = startcolor("darkblue")
+ local tlcolor = startcolor("darkyellow")
+ local black = stopcolor
+ for unicode, character in next, characters do
+ local mathkern = character.mathkern
+ if mathkern then
+ -- more efficient would be co collect more in one pdf
+ -- directive but this is hardly used so not worth the
+ -- effort
+ local width = character.width or 0
+ local height = character.height or 0
+ local depth = character.depth or 0
+ local list = { }
+ local br = mathkern.bottom_right
+ local tr = mathkern.top_right
+ local bl = mathkern.bottom_left
+ local tl = mathkern.top_left
+ if br then
+ ladder(list,brcolor,black,br,width,1,height)
+ end
+ if tr then
+ ladder(list,trcolor,black,tr,width,1,-depth)
+ end
+ if bl then
+ ladder(list,blcolor,black,bl,0,-1,height)
+ end
+ if tl then
+ ladder(list,tlcolor,black,tl,0,-1,-depth)
+ end
+ if #list > 0 then
+ local commands = character.commands
+ if commands then
+ character.commands = appendcommandtable(commands,list)
+ else
+ list[#list+1] = charcommand[unicode]
+ character.commands = list
+ end
+ end
+ end
+ end
+ end
+end
+
+local specification = {
+ name = "staircase",
+ description = "show staircase kerns",
+ position=1,
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+registerotffeature(specification)
+registerafmfeature(specification)
diff --git a/tex/context/base/mkiv/font-imp-unicode.lua b/tex/context/base/mkiv/font-imp-unicode.lua
new file mode 100644
index 000000000..ddb965ec9
--- /dev/null
+++ b/tex/context/base/mkiv/font-imp-unicode.lua
@@ -0,0 +1,82 @@
+if not modules then modules = { } end modules ['font-imp-unicode'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not context then return end
+
+local next = next
+
+local fonts = fonts
+local helpers = fonts.helpers
+local constructors = fonts.constructors
+local registerotffeature = fonts.handlers.otf.features.register
+
+local extraprivates = helpers.extraprivates
+local addprivate = helpers.addprivate
+
+local function initialize(tfmdata)
+ for i=1,#extraprivates do
+ local e = extraprivates[i]
+ local c = e[2](tfmdata)
+ if c then
+ addprivate(tfmdata, e[1], c)
+ end
+ end
+end
+
+constructors.newfeatures.otf.register {
+ name = "extraprivates",
+ description = "extra privates",
+ default = true,
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+local tounicode = fonts.mappings.tounicode
+
+local function initialize(tfmdata,key,value)
+ if value == "ligatures" then
+ local private = fonts.constructors and fonts.constructors.privateoffset or 0xF0000
+ local collected = fonts.handlers.otf.readers.getcomponents(tfmdata.shared.rawdata)
+ if collected and next(collected)then
+ for unicode, char in next, tfmdata.characters do
+ local u = collected[unicode]
+ if u then
+ local n = #u
+ for i=1,n do
+ if u[i] > private then
+ n = 0
+ break
+ end
+ end
+ if n > 0 then
+ if n == 1 then
+ u = u[1]
+ end
+ char.unicode = u
+ char.tounicode = tounicode(u)
+ end
+ end
+ end
+ end
+ end
+end
+
+-- forceunicodes=ligatures : aggressive lig resolving (e.g. for emoji)
+--
+-- kind of like: \enabletrackers[fonts.mapping.forceligatures]
+
+registerotffeature {
+ name = "forceunicodes",
+ description = "forceunicodes",
+ manipulators = {
+ base = initialize,
+ node = initialize,
+ }
+}
diff --git a/tex/context/base/mkiv/font-ini.lua b/tex/context/base/mkiv/font-ini.lua
index 3d5dd27a2..462e30bf9 100644
--- a/tex/context/base/mkiv/font-ini.lua
+++ b/tex/context/base/mkiv/font-ini.lua
@@ -10,22 +10,45 @@ if not modules then modules = { } end modules ['font-ini'] = {
<p>Not much is happening here.</p>
--ldx]]--
-local allocate = utilities.storage.allocate
+local allocate = utilities.storage.allocate
+local sortedhash = table.sortedhash
-fonts = fonts or { }
-local fonts = fonts
+fonts = fonts or { }
+local fonts = fonts
-fonts.hashes = fonts.hashes or { 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 !
+local identifiers = allocate()
-fonts.analyzers = { } -- not needed here
-fonts.readers = { }
-fonts.definers = { methods = { } }
-fonts.loggers = { register = function() end }
+fonts.hashes = fonts.hashes or { identifiers = identifiers }
+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.definers = { methods = { } }
+fonts.loggers = { register = function() end }
if context then
+
+ font.originaleach = font.each
+
+ function font.each()
+ return sortedhash(identifiers)
+ end
+
fontloader = nil
+
end
+
+-- Outside context one can bump textbase to some higher value but only the
+-- textbase given here is officially supported (read: bug testing etc will
+-- use the values below).
+
+fonts.privateoffsets = {
+ textbase = 0xF0000, -- used for hidden (opentype features)
+ textextrabase = 0xFD000, -- used for visible by name
+ mathextrabase = 0xFE000, -- used for visible by code
+ mathbase = 0xFF000, -- used for hidden (virtual math)
+ keepnames = false, -- when set to true names are always kept (not for context)
+}
diff --git a/tex/context/base/mkiv/font-ini.mkvi b/tex/context/base/mkiv/font-ini.mkvi
index 693182919..dd8a5f148 100644
--- a/tex/context/base/mkiv/font-ini.mkvi
+++ b/tex/context/base/mkiv/font-ini.mkvi
@@ -341,12 +341,16 @@
\the\everybodyfont
\settrue\c_font_synchronize}
+\let\savedfont\empty
+
+\installmacrostack\savedfont
+
\unexpanded\def\savefont
{\edef\savedfont{\the\font}% gives \csname
- \pushmacro\savedfont}
+ \push_macro_savedfont}
\unexpanded\def\restorefont
- {\popmacro\savedfont
+ {\pop_macro_savedfont
\savedfont}
\unexpanded\def\pushcurrentfont
@@ -424,7 +428,7 @@
%
% \def\normalizebodyfontsize_indeed#macro#body%
% {\edef#macro{\ctxcommand{nbfs(\number\dimexpr#body,\number\fontdigits)}}%
-% \global\expandafter\let\csname\??fontnormalizedbody\number\fontdigits:\number\dimexpr#body\endcsname#macro}
+% \expandafter\glet\csname\??fontnormalizedbody\number\fontdigits:\number\dimexpr#body\endcsname#macro}
%
% \def\thenormalizedbodyfontsize#body%
% {\ctxcommand{nbfs(\number\dimexpr#body\relax,\number\fontdigits)}}
@@ -439,7 +443,7 @@
\def\normalizebodyfontsize_indeed#macro#body%
{\edef#macro{\clf_nbfs\dimexpr#body\relax}%
- \global\expandafter\let\csname\??fontnormalizedbody\number\dimexpr#body\endcsname#macro}
+ \expandafter\glet\csname\??fontnormalizedbody\number\dimexpr#body\endcsname#macro}
\def\thenormalizedbodyfontsize#body%
{\clf_nbfs\dimexpr#body\relax}
@@ -583,8 +587,7 @@
\def\font_basics_define_fontstyle[#commands][#style]% style: rm ss tt ...
{\ifcsname\??fontstyleknown#style\endcsname \else % can be delayed till used (cg, hw)
\font_helpers_register_style{#style}%
- % todo: apptoks
- \t_font_style_commands\expandafter{\the\t_font_style_commands\m_font_style_command{#style}}%
+ \toksapp\t_font_style_commands{\m_font_style_command{#style}}%
\fi
\processcommalist[#commands]{\font_basics_define_fontstyle_indeed{#style}}}
@@ -595,17 +598,14 @@
\unexpanded\def\definefontsize[#size]%
{\ifcsname\??fontsizeknown#size\endcsname \else
\font_helpers_register_size{#size}%
- \t_font_size_commands\expandafter{\the\t_font_size_commands
- \m_font_size_command{#size}}%
+ \toksapp\t_font_size_commands{\m_font_size_command{#size}}%
\fi
\font_helpers_check_fontname_combinations}
\unexpanded\def\definefontalternative[#alternative]%
{\ifcsname\??fontalternativeknown#alternative\endcsname \else
\font_helpers_register_alternative{#alternative}%
- % todo: apptoks
- \t_font_alternative_commands\expandafter{\the\t_font_alternative_commands
- \m_font_alternative_command{#alternative}}%
+ \toksapp\t_font_alternative_commands{\m_font_alternative_command{#alternative}}%
\fi
\font_helpers_check_fontname_combinations}
@@ -775,7 +775,7 @@
\unexpanded\def\font_helpers_low_level_define#specification#csname%
{% we can now set more at the lua end
- \global\let\somefontname\defaultfontfile
+ \glet\somefontname\defaultfontfile
\let\somefontsize\empty
\clf_definefont_one{\detokenize\expandafter{\normalexpanded{#specification}}}% the escapestring catches at \somedimen
% sets \scaledfontmode and \somefontname and \somefontsize
@@ -912,7 +912,7 @@
%D The following macros are used at the \LUA\ end. Watch the \type {\normal}
%D hackery: this makes the mkvi parser happy.
-% \normaldef\fntsetdefname {\global\let\somefontname\defaultfontfile} % do before calling
+% \normaldef\fntsetdefname {\glet\somefontname\defaultfontfile} % do before calling
% \normaldef\fntsetnopsize {\let\somefontsize\empty} % do before calling
% \normaldef\fntsetsomename{\normalgdef\somefontname} % takes argument
% \normaldef\fntsetsomesize{\normaldef\somefontsize} % takes argument
@@ -1038,7 +1038,7 @@
{\begingroup
\font_basics_define_font[#name][#specification][#settings]%
\csname#name\endcsname
- \global\let\lastglobalrawfontcall\lastrawfontcall
+ \glet\lastglobalrawfontcall\lastrawfontcall
\endgroup
\expandafter\let\csname#name\endcsname\lastglobalrawfontcall}
@@ -1377,16 +1377,16 @@
%D settings (just to be sure, as it's not really needed).
\def\font_basics_define_body_font_environment_empty[#body][#settings][#dummy]%
- {\pushmacro\fontclass
+ {\push_macro_fontclass
\let\fontclass\empty
\font_basics_define_body_font_environment_class[][#body][#settings]%
- \popmacro\fontclass}
+ \pop_macro_fontclass}
\def\font_basics_define_body_font_environment_unset[#body][#dummya][#dummyb]%
- {\pushmacro\fontclass
+ {\push_macro_fontclass
\let\fontclass\empty
\font_basics_define_body_font_environment_class[][#body][]%
- \popmacro\fontclass}
+ \pop_macro_fontclass}
%D We don't check too soon as we can refer to later definitions.
@@ -1397,13 +1397,13 @@
\ifcsname\??fontenvironmentknown#class#normalizedbody\endcsname
% environment and size already defined
\else\ifproductionrun
- \pushmacro\fontclass
+ \push_macro_fontclass
\edef\fontclass{#class}%
\font_helpers_register_environment{#class}{#normalizedbody}%
\settrue\c_font_defining_environment_state
\font_helpers_define_unknown_font{#normalizedbody}% current class
\setfalse\c_font_defining_environment_state
- \popmacro\fontclass
+ \pop_macro_fontclass
\fi\fi
\font_helpers_register_fontbody{#normalizedbody}}
@@ -1527,12 +1527,12 @@
\fi}
\def\font_basics_define_body_font_class_given[#1][#2][#3]#4%
- {\pushmacro\fontclass
+ {\push_macro_fontclass
\doifelse{#4}\s!default
{\let\fontclass\empty}
{\def\fontclass{#4}}%
\definebodyfont[#1][#2][#3]%
- \popmacro\fontclass}
+ \pop_macro_fontclass}
\def\font_basics_define_body_font_class_known
{\ifthirdargument
@@ -1644,13 +1644,13 @@
\unexpanded\def\font_basics_define_body_font_yes_xx[#one#two#rest=#value]% global
{\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi
- \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-1\endcsname\undefined
+ \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-1\endcsname\undefined
\unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname
{\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-0}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
- \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-2\endcsname\undefined
+ \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-2\endcsname\undefined
\unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname
{\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-4}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
- \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-3\endcsname\undefined
+ \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-3\endcsname\undefined
\unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname
{\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-5}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
}
@@ -1673,9 +1673,9 @@
\unexpanded\def\font_basics_define_body_font_yes_mm[#one#two#rest=#value]% global
{%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi
- \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined
- % \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined
- % \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined
+ \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined
+ % \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined
+ % \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined
\unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\s!mm-#one#two#rest\endcsname
{\font_helpers_trigger{\m_font_asked_body-\s!mm-#one#two#rest}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
}
@@ -1727,7 +1727,8 @@
\font_helpers_process_style_list{\font_helpers_define_unknown_check_definitions{#body}}%
\ifconditional\c_font_defining_state
\ifconditional\c_font_defining_environment_state\else
- \showmessage\m!fonts{14}{#body}% main
+ %\showmessage\m!fonts{14}{#body}% main
+ \clf_registerunknownbodysize{#body}%
\fi
\setfalse\c_font_defining_state
\font_helpers_register_fontbody{#body}%
@@ -1741,13 +1742,6 @@
\fi
\fi}
-% \def\font_helpers_define_unknown_check_sizes#body#relativesize%
-% {\ifcsname\??fontenvironments\s!default#relativesize\endcsname % fontclass ?
-% % how \lastnamedcs here
-% \expandafter\normalizebodyfontsize\csname\??fontenvironments#body#relativesize\endcsname{\csname\??fontenvironments\s!default#relativesize\endcsname\dimexpr#body\relax}%
-% \settrue\c_font_defining_state
-% \fi}
-
\def\font_helpers_define_unknown_check_sizes#body#relativesize%
{\ifcsname\??fontenvironments\s!default#relativesize\endcsname % fontclass ?
\expandafter\normalizebodyfontsize\csname\??fontenvironments#body#relativesize\endcsname{\csname\??fontenvironments\s!default#relativesize\endcsname\dimexpr#body\relax}%
@@ -2363,7 +2357,7 @@
\noexpand\edef\noexpand\xtextface {\currentbodyfontdimension\s!x }%
\noexpand\edef\noexpand\xxtextface {\currentbodyfontdimension\s!xx }%
}%
- \global\expandafter\let\csname\??fontbodyfaces\fontbody\endcsname\font_basics_set_faces}
+ \expandafter\glet\csname\??fontbodyfaces\fontbody\endcsname\font_basics_set_faces}
% \def\currentbodyfontdimension#parameter%
% {\the\dimexpr
@@ -2505,15 +2499,15 @@
%D \stoptyping
% \unexpanded\def\usebodyfont[#1]%
-% {\pushmacro\fontclass
+% {\push_macro_fontclass
% \switchtobodyfont[#1]%
-% \popmacro\fontclass
+% \pop_macro_fontclass
% \ifx\fontclass\empty\else\setupbodyfont\relax\fi}
% \unexpanded\def\usebodyfont[#1]%
-% {\pushmacro\fontclass
+% {\push_macro_fontclass
% \font_helpers_set_font\zerocount{#1}%
-% \popmacro\fontclass
+% \pop_macro_fontclass
% \ifx\fontclass\empty \else
% \font_basics_setupbodyfont_nop
% \fi}
@@ -2716,7 +2710,7 @@
\unexpanded\def\font_basics_predefine#1#2%
{\font_basics_defined_font_yes[#2]%
- \global\expandafter\let\csname#1\expandafter\endcsname\csname\v_font_identifier_basic\endcsname}
+ \expandafter\glet\csname#1\expandafter\endcsname\csname\v_font_identifier_basic\endcsname}
\unexpanded\def\font_basics_predefined#1%
{\font_basics_predefine{\??predefinedfont#1}{#1}}
@@ -2763,7 +2757,26 @@
\expandafter\getprivatechar
\fi}
-% new
+%D Some fonts can have color specifiers:
+%D
+%D \starttyping
+%D \definefontfeature[seguiemj-cl][default][colr=yes,ccmp=yes,dist=yes]
+%D \definefontsynonym[emoji][seguiemj*seguiemj-cl]
+%D
+%D \definecolor[emoji-red] [r=.4]
+%D \definecolor[emoji-gray][s=1,t=.5,a=1]
+%D
+%D %definefontcolorpalette [emoji-r] [emoji-red,emoji-gray,textcolor] % bad
+%D \definefontcolorpalette [emoji-r] [emoji-red,emoji-gray] % okay
+%D
+%D \definefontfeature[seguiemj-r][ccmp=yes,dist=yes,colr=emoji-r]
+%D
+%D \definefont[MyEmojiR][seguiemj*seguiemj-r @ 100pt]
+%D
+%D \startTEXpage[offset=10pt]
+%D \MyEmojiR\resolvedemoji{triangular ruler}
+%D \stopTEXpage
+%D \stoptyping
\unexpanded\def\definefontcolorpalette
{\dodoubleargument\font_define_color_palette}
diff --git a/tex/context/base/mkiv/font-lib.mkvi b/tex/context/base/mkiv/font-lib.mkvi
index 24ab68781..3cff81751 100644
--- a/tex/context/base/mkiv/font-lib.mkvi
+++ b/tex/context/base/mkiv/font-lib.mkvi
@@ -26,22 +26,27 @@
% the otf font loader:
+% helpers
+
+
\registerctxluafile{font-otr}{optimize} % opentype fontloader
\registerctxluafile{font-web}{} % opentype fontloader
\registerctxluafile{font-cff}{optimize} % quadratic outlines
\registerctxluafile{font-ttf}{optimize} % cubic outlines
\registerctxluafile{font-dsp}{optimize} % ... for this one
\registerctxluafile{font-hsh}{} % hashes used by context
-\registerctxluafile{font-nod}{}
+\registerctxluafile{font-vfc}{}
+\registerctxluafile{font-prv}{} % needs hashes
+\registerctxluafile{font-nod}{optimize}
\registerctxluafile{font-oti}{} % otf initialization
\registerctxluafile{font-ott}{} % otf tables (first)
\registerctxluafile{font-otl}{}
\registerctxluafile{font-oto}{}
-\registerctxluafile{font-otj}{}
+\registerctxluafile{font-otj}{optimize}
\registerctxluafile{font-oup}{}
\registerctxluafile{font-ota}{}
-\registerctxluafile{font-ots}{}
-\registerctxluafile{font-otd}{}
+\registerctxluafile{font-ots}{optimize}
+\registerctxluafile{font-otd}{optimize}
\registerctxluafile{font-otc}{}
\registerctxluafile{font-oth}{}
\registerctxluafile{font-osd}{}
@@ -55,7 +60,12 @@
% tfm
-\registerctxluafile{font-tfm}{}
+\doifelsefileexists {font-tpk.lua} {
+ \registerctxluafile{font-tpk}{optimize}
+ \registerctxluafile{font-tfm}{}
+} {
+ \registerctxluafile{font-tfm}{}
+}
% name database
@@ -87,7 +97,28 @@
\registerctxluafile{font-def}{}
\registerctxluafile{font-ctx}{} % after def as it overloads
-\registerctxluafile{font-ext}{}
+% extensions, order matters
+
+\registerctxluafile{font-imp-ligatures}{}
+\registerctxluafile{font-imp-tex}{}
+\registerctxluafile{font-imp-reorder}{}
+\registerctxluafile{font-imp-properties}{}
+\registerctxluafile{font-imp-unicode}{}
+\registerctxluafile{font-imp-math}{}
+\registerctxluafile{font-imp-notused}{}
+\registerctxluafile{font-imp-effects}{}
+\registerctxluafile{font-imp-quality}{}
+\registerctxluafile{font-imp-italics}{}
+\registerctxluafile{font-imp-dimensions}{}
+
+\doifelsefileexists{font-imp-scripts.lua} {
+ \registerctxluafile{font-imp-scripts}{}
+} {
+ % not yet, lmtx feature
+}
+
+\registerctxluafile{font-imp-tracing}{} % comes last!
+
\registerctxluafile{font-fbk}{}
\registerctxluafile{font-aux}{}
diff --git a/tex/context/base/mkiv/font-map.lua b/tex/context/base/mkiv/font-map.lua
index 66cf2db39..d931b822e 100644
--- a/tex/context/base/mkiv/font-map.lua
+++ b/tex/context/base/mkiv/font-map.lua
@@ -168,44 +168,73 @@ local function tounicode16sequence(unicodes)
return concat(t)
end
-local function tounicode(unicode)
- if type(unicode) == "table" then
- local t = { }
- for l=1,#unicode do
- local u = unicode[l]
- if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then
- t[l] = f_single(u)
- else
- u = u - 0x10000
- t[l] = f_double(rshift(u,10)+0xD800,u%1024+0xDC00)
- end
- end
- return concat(t)
- else
- if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then
- return f_single(unicode)
- else
- unicode = unicode - 0x10000
- return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00)
- end
- end
-end
+-- local function tounicode(unicode)
+-- if type(unicode) == "table" then
+-- local t = { }
+-- for l=1,#unicode do
+-- local u = unicode[l]
+-- if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then
+-- t[l] = f_single(u)
+-- else
+-- u = u - 0x10000
+-- t[l] = f_double(rshift(u,10)+0xD800,u%1024+0xDC00)
+-- end
+-- end
+-- return concat(t)
+-- else
+-- if unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then
+-- return f_single(unicode)
+-- else
+-- unicode = unicode - 0x10000
+-- return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00)
+-- end
+-- end
+-- end
--- no real gain on runs
+local unknown = f_single(0xFFFD)
--- local hash = table.setmetatableindex(function(t,u)
+-- local function tounicode(unicode)
+-- if type(unicode) == "table" then
+-- local t = { }
+-- for l=1,#unicode do
+-- t[l] = tounicode(unicode[l])
+-- end
+-- return concat(t)
+-- elseif unicode >= 0x00E000 and unicode <= 0x00F8FF then
+-- return unknown
+-- elseif unicode >= 0x0F0000 and unicode <= 0x0FFFFF then
+-- return unknown
+-- elseif unicode >= 0x100000 and unicode <= 0x10FFFF then
+-- return unknown
+-- elseif unicode < 0xD7FF or (unicode > 0xDFFF and unicode <= 0xFFFF) then
+-- return f_single(unicode)
+-- else
+-- unicode = unicode - 0x10000
+-- return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00)
+-- end
+-- end
+
+-- local hash = table.setmetatableindex(function(t,k)
-- local v
--- if u < 0xD7FF or (u > 0xDFFF and u <= 0xFFFF) then
--- v = f_single(u)
+-- if k >= 0x00E000 and k <= 0x00F8FF then
+-- v = unknown
+-- elseif k >= 0x0F0000 and k <= 0x0FFFFF then
+-- v = unknown
+-- elseif k >= 0x100000 and k <= 0x10FFFF then
+-- v = unknown
+-- elseif k < 0xD7FF or (k > 0xDFFF and k <= 0xFFFF) then
+-- v = f_single(k)
-- else
--- u = u - 0x10000
--- v = f_double(rshift(u,10)+0xD800,u%1024+0xDC00)
+-- local k = k - 0x10000
+-- v = f_double(rshift(k,10)+0xD800,k%1024+0xDC00)
-- end
--- t[u] = v
+-- t[k] = v
-- return v
-- end)
--
--- local function tounicode(unicode,name)
+-- table.makeweak(hash)
+--
+-- local function tounicode(unicode)
-- if type(unicode) == "table" then
-- local t = { }
-- for l=1,#unicode do
@@ -217,6 +246,69 @@ end
-- end
-- end
+local hash = { }
+local conc = { }
+
+-- table.makeweak(hash)
+
+-- table.setmetatableindex(hash,function(t,k)
+-- if type(k) == "table" then
+-- local n = #k
+-- for l=1,n do
+-- conc[l] = hash[k[l]]
+-- end
+-- return concat(conc,"",1,n)
+-- end
+-- local v
+-- if k >= 0x00E000 and k <= 0x00F8FF then
+-- v = unknown
+-- elseif k >= 0x0F0000 and k <= 0x0FFFFF then
+-- v = unknown
+-- elseif k >= 0x100000 and k <= 0x10FFFF then
+-- v = unknown
+-- elseif k < 0xD7FF or (k > 0xDFFF and k <= 0xFFFF) then
+-- v = f_single(k)
+-- else
+-- local k = k - 0x10000
+-- v = f_double(rshift(k,10)+0xD800,k%1024+0xDC00)
+-- end
+-- t[k] = v
+-- return v
+-- end)
+--
+-- local function tounicode(unicode)
+-- return hash[unicode]
+-- end
+
+table.setmetatableindex(hash,function(t,k)
+ if k < 0xD7FF or (k > 0xDFFF and k <= 0xFFFF) then
+ v = f_single(k)
+ else
+ local k = k - 0x10000
+ v = f_double(rshift(k,10)+0xD800,k%1024+0xDC00)
+ end
+ t[k] = v
+ return v
+end)
+
+local function tounicode(k)
+ if type(k) == "table" then
+ local n = #k
+ for l=1,n do
+ conc[l] = hash[k[l]]
+ end
+ return concat(conc,"",1,n)
+ elseif k >= 0x00E000 and k <= 0x00F8FF then
+ return unknown
+ elseif k >= 0x0F0000 and k <= 0x0FFFFF then
+ return unknown
+ elseif k >= 0x100000 and k <= 0x10FFFF then
+ return unknown
+ else
+ return hash[k]
+ end
+end
+
local function fromunicode16(str)
if #str == 4 then
return tonumber(str,16)
@@ -431,7 +523,8 @@ function mappings.addtounicode(data,filename,checklookups,forceligatures)
glyph.unicode = unicode
end
else
- local t, n = { }, 0
+ local t = { }
+ local n = 0
for l=1,nsplit do
local base = split[l]
local u = unicodes[base] or unicodevector[base] or contextvector[name]
@@ -487,12 +580,17 @@ function mappings.addtounicode(data,filename,checklookups,forceligatures)
missing[du] = true
nofmissing = nofmissing + 1
end
+ else
+ -- maybe a message or so
end
end
else
local overload = overloads[du]
if overload then
glyph.unicode = overload.unicode
+ elseif not glyph.unicode then
+ missing[du] = true
+ nofmissing = nofmissing + 1
end
end
end
diff --git a/tex/context/base/mkiv/font-mat.mkvi b/tex/context/base/mkiv/font-mat.mkvi
index 0134f3fe6..64810d327 100644
--- a/tex/context/base/mkiv/font-mat.mkvi
+++ b/tex/context/base/mkiv/font-mat.mkvi
@@ -263,12 +263,12 @@
\fi}
\def\font_helpers_bidirectional_mathstrategy_nop_changed
- {\textfont \c_font_fam_mr_rl\textfont \c_font_fam_mr
- \scriptfont \c_font_fam_mr_rl\scriptfont \c_font_fam_mr
- \scriptscriptfont\c_font_fam_mr_rl\scriptscriptfont\c_font_fam_mr
- \textfont \c_font_fam_mr_lr\textfont \c_font_fam_mr
+ {\textfont \c_font_fam_mr_lr\textfont \c_font_fam_mr
\scriptfont \c_font_fam_mr_lr\scriptfont \c_font_fam_mr
- \scriptscriptfont\c_font_fam_mr_lr\scriptscriptfont\c_font_fam_mr}
+ \scriptscriptfont\c_font_fam_mr_lr\scriptscriptfont\c_font_fam_mr
+ \textfont \c_font_fam_mr_rl\textfont \c_font_fam_mr
+ \scriptfont \c_font_fam_mr_rl\scriptfont \c_font_fam_mr
+ \scriptscriptfont\c_font_fam_mr_rl\scriptscriptfont\c_font_fam_mr}
\appendtoks
\ifconditional\c_font_bidirectional_mathstrategy
@@ -313,12 +313,12 @@
{\textfont \c_font_fam_mb \textfont \c_font_fam_mr
\scriptfont \c_font_fam_mb \scriptfont \c_font_fam_mr
\scriptscriptfont\c_font_fam_mb \scriptscriptfont\c_font_fam_mr
- \textfont \c_font_fam_mb_rl\textfont \c_font_fam_mr_rl
- \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mr_rl
- \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mr_rl
\textfont \c_font_fam_mb_lr\textfont \c_font_fam_mr_lr
\scriptfont \c_font_fam_mb_lr\scriptfont \c_font_fam_mr_lr
- \scriptscriptfont\c_font_fam_mb_lr\scriptscriptfont\c_font_fam_mr_lr}
+ \scriptscriptfont\c_font_fam_mb_lr\scriptscriptfont\c_font_fam_mr_lr
+ \textfont \c_font_fam_mb_rl\textfont \c_font_fam_mr_rl
+ \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mr_rl
+ \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mr_rl}
\def\font_helpers_apply_complete_bold_mathstrategy
{\ifconditional\c_font_complete_bold_mathstrategy
@@ -425,13 +425,16 @@
\ifdefined\mathdefault \else \let\mathdefault\relax \fi
+\newconditional\c_math_bold
+
\unexpanded\def\mr % math regular
{\ifmmode
\font_helpers_synchronize_math_family_mr
\else
\font_helpers_set_current_font_alternative\s!mr
\fi
- \mathdefault}
+ \mathdefault
+ \setfalse\c_math_bold}
\unexpanded\def\mb % math bold
{\ifmmode
@@ -439,12 +442,17 @@
\else
\font_helpers_set_current_font_alternative\s!mb
\fi
- \mathdefault}
+ \mathdefault
+ \settrue\c_math_bold}
\appendtoks
\font_helpers_synchronize_math_family % auto bold
\to \everymathematics
+\appendtoks
+ \ifconditional\c_math_bold\mb\fi
+\to \everymathematics
+
%D \macros
%D {bigmath,nobigmath}
%D
diff --git a/tex/context/base/mkiv/font-mis.lua b/tex/context/base/mkiv/font-mis.lua
index e1f158c83..c75b92984 100644
--- a/tex/context/base/mkiv/font-mis.lua
+++ b/tex/context/base/mkiv/font-mis.lua
@@ -8,20 +8,20 @@ if not modules then modules = { } end modules ['font-mis'] = {
fonts = fonts or { }
-fonts.helpers = fonts.helpers or { }
-local helpers = fonts.helpers
+local helpers = fonts.helpers or { }
+fonts.helpers = helpers
-fonts.handlers = fonts.handlers or { }
-local handlers = fonts.handlers
+local handlers = fonts.handlers or { }
+fonts.handlers = handlers
-handlers.otf = handlers.otf or { }
-local otf = handlers.otf
+local otf = handlers.otf or { }
+handlers.otf = otf
local readers = otf.readers
if readers then
- otf.version = otf.version or 3.103
+ otf.version = otf.version or 3.107
otf.cache = otf.cache or containers.define("fonts", "otl", otf.version, true)
function fonts.helpers.getfeatures(name,save)
diff --git a/tex/context/base/mkiv/font-mps.lua b/tex/context/base/mkiv/font-mps.lua
index cde34f2ae..895835958 100644
--- a/tex/context/base/mkiv/font-mps.lua
+++ b/tex/context/base/mkiv/font-mps.lua
@@ -6,6 +6,7 @@ if not modules then modules = { } end modules ['font-mps'] = {
license = "see context related readme files"
}
+local tostring = tostring
local concat = table.concat
local formatters = string.formatters
@@ -35,6 +36,17 @@ local f_draw = formatters["draw %s;"]
local f_boundingbox = formatters["((%.6F,%.6F)--(%.6F,%.6F)--(%.6F,%.6F)--(%.6F,%.6F)--cycle)"]
local f_vertical = formatters["((%.6F,%.6F)--(%.6F,%.6F))"]
+directives.register("metapost.stripzeros", function()
+
+ f_moveto = formatters["(%.6N,%.6N)"]
+ f_lineto = formatters["--(%.6N,%.6N)"]
+ f_curveto = formatters["..controls(%.6N,%.6N)and(%.6N,%.6N)..(%.6N,%.6N)"]
+
+ f_boundingbox = formatters["((%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--(%.6N,%.6N)--cycle)"]
+ f_vertical = formatters["((%.6N,%.6N)--(%.6N,%.6N))"]
+
+end)
+
function metapost.boundingbox(d,factor)
local bounds = d.boundingbox
local factor = factor or 1
@@ -97,9 +109,12 @@ function metapost.paths(d,xfactor,yfactor)
elseif operator =="q" then -- "quadraticto"
size = size + 1
-- first is always a moveto
- local l_x, l_y = xfactor*sequence[i-2], yfactor*sequence[i-1]
- local m_x, m_y = xfactor*sequence[i+1], yfactor*sequence[i+2]
- local r_x, r_y = xfactor*sequence[i+3], yfactor*sequence[i+4]
+ local l_x = xfactor*sequence[i-2]
+ local l_y = yfactor*sequence[i-1]
+ local m_x = xfactor*sequence[i+1]
+ local m_y = yfactor*sequence[i+2]
+ local r_x = xfactor*sequence[i+3]
+ local r_y = yfactor*sequence[i+4]
path[size] = f_curveto (
l_x + 2/3 * (m_x-l_x),
l_y + 2/3 * (m_y-l_y),
@@ -137,9 +152,12 @@ function metapost.paths(d,xfactor,yfactor)
size = size + 1
-- first is always a moveto
local prev = segments[i-1]
- local l_x, l_y = xfactor*prev[#prev-2], yfactor*prev[#prev-1]
- local m_x, m_y = xfactor*segment[1], yfactor*segment[2]
- local r_x, r_y = xfactor*segment[3], yfactor*segment[4]
+ local l_x = xfactor*prev[#prev-2]
+ local l_y = yfactor*prev[#prev-1]
+ local m_x = xfactor*segment[1]
+ local m_y = yfactor*segment[2]
+ local r_x = xfactor*segment[3]
+ local r_y = yfactor*segment[4]
path[size] = f_curveto (
l_x + 2/3 * (m_x-l_x),
l_y + 2/3 * (m_y-l_y),
@@ -196,7 +214,10 @@ function metapost.maxbounds(data,index,factor)
local boundingbox = glyph.boundingbox
local xmin, ymin, xmax, ymax
if not maxbounds then
- xmin, ymin, xmax, ymax = 0, 0, 0, 0
+ xmin = 0
+ ymin = 0
+ xmax = 0
+ ymax = 0
for i=1,#glyphs do
local d = glyphs[i]
if d then
@@ -240,45 +261,52 @@ end
-- right time. It's probably why I like watching https://www.youtube.com/watch?v=c5FqpddnJmc
-- so much: precisely (and perfectly) timed too.
-local nodecodes = nodes.nodecodes -- no nuts yet
-
-local glyph_code = nodecodes.glyph
-local disc_code = nodecodes.disc
-local kern_code = nodecodes.kern
-local glue_code = nodecodes.glue
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local rule_code = nodecodes.rule
-
-local normal_rule = nodes.rulecodes.normal
-
-local nuts = nodes.nuts
-local getnext = nuts.getnext
-local getid = nuts.getid
-local getlist = nuts.getlist
-local getchar = nuts.getchar
-local getfont = nuts.getfont
-local getsubtype = nuts.getsubtype
-local getfield = nuts.getfield
-local getbox = nuts.getbox
-local getwhd = nuts.getwhd
-local getkern = nuts.getkern
-local getshift = nuts.getshift
-local getwidth = nuts.getwidth
-local getheight = nuts.getheight
-local getdepth = nuts.getdepth
-
-local effective_glue = nuts.effective_glue
-
-local characters = fonts.hashes.characters
-local parameters = fonts.hashes.parameters
-local shapes = fonts.hashes.shapes
-local topaths = metapost.paths
-
-local f_code = formatters["mfun_do_outline_text_flush(%q,%i,%.6F,%.6F)(%,t);"]
-local f_rule = formatters["mfun_do_outline_rule_flush(%q,%.6F,%.6F,%.6F,%.6F);"]
-local f_bounds = formatters["checkbounds(%.6F,%.6F,%.6F,%.6F);"]
-local s_nothing = "(origin scaled 10)"
+local nodecodes = nodes.nodecodes -- no nuts yet
+local rulecodes = nodes.rulecodes
+
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local rule_code = nodecodes.rule
+
+local normalrule_code = rulecodes.normal
+
+local nuts = nodes.nuts
+local getnext = nuts.getnext
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getsubtype = nuts.getsubtype
+local getfield = nuts.getfield
+local getbox = nuts.getbox
+local getwhd = nuts.getwhd
+local getkern = nuts.getkern
+local getshift = nuts.getshift
+local getwidth = nuts.getwidth
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
+local getexpansion = nuts.getexpansion
+local isglyph = nuts.isglyph
+
+local effective_glue = nuts.effective_glue
+
+local characters = fonts.hashes.characters
+local parameters = fonts.hashes.parameters
+local shapes = fonts.hashes.shapes
+local topaths = metapost.paths
+
+local f_code = formatters["mfun_do_outline_text_flush(%q,%i,%.6F,%.6F,%q)(%,t);"]
+local f_rule = formatters["mfun_do_outline_rule_flush(%q,%.6F,%.6F,%.6F,%.6F);"]
+local f_bounds = formatters["checkbounds(%.6F,%.6F,%.6F,%.6F);"]
+local s_nothing = "(origin scaled 10)"
+
+directives.register("metapost.stripzeros", function()
+ f_code = formatters["mfun_do_outline_text_flush(%q,%i,%.6N,%.6N,%q)(%,t);"]
+ f_rule = formatters["mfun_do_outline_rule_flush(%q,%.6N,%.6N,%.6N,%.6N);"]
+ f_bounds = formatters["checkbounds(%.6N,%.6N,%.6N,%.6N);"]
+end)
local sc = 10
local fc = number.dimenfactors.bp * sc / 10
@@ -302,13 +330,14 @@ function metapost.output(kind,font,char,advance,shift,ex)
local advance = advance or 0
local exfactor = ex or 0
local wfactor = 1
+ local detail = kind == "p" and tostring(char) or ""
if exfactor ~= 0 then
wfactor = (1+(ex/units)/1000)
xfactor = xfactor * wfactor
end
local paths = topaths(glyf,xfactor,yfactor)
if paths then
- local code = f_code(kind,#paths,advance,shift,paths)
+ local code = f_code(kind,#paths,advance,shift,detail,paths)
return code, character.width * fc * wfactor
else
return "", 0
@@ -337,9 +366,9 @@ function fonts.metapost.boxtomp(n,kind)
horizontal = function(parent,current,xoffset,yoffset)
local dx = 0
while current do
- local id = getid(current)
- if id == glyph_code then
- local code, width = metapost.output(kind,getfont(current),getchar(current),xoffset+dx,yoffset,getfield(current,"expansion_factor"))
+ local char, id = isglyph(current)
+ if char then
+ local code, width = metapost.output(kind,id,char,xoffset+dx,yoffset,getexpansion(current))
result[#result+1] = code
dx = dx + width
elseif id == disc_code then
@@ -374,7 +403,7 @@ function fonts.metapost.boxtomp(n,kind)
dp = getdepth(parent)
end
local hd = (ht + dp) * fc
- if hd ~= 0 and getsubtype(current) == normal_rule then
+ if hd ~= 0 and getsubtype(current) == normalrule_code then
result[#result+1] = f_rule(kind,xoffset+dx+wd/2,yoffset+hd/2,wd,hd)
end
dx = dx + wd
diff --git a/tex/context/base/mkiv/font-nod.lua b/tex/context/base/mkiv/font-nod.lua
index 2670a924b..a0eb88a25 100644
--- a/tex/context/base/mkiv/font-nod.lua
+++ b/tex/context/base/mkiv/font-nod.lua
@@ -32,6 +32,10 @@ nodes.tasks = tasks
local handlers = nodes.handlers or { }
nodes.handlers = handlers
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
local injections = nodes.injections or { }
nodes.injections = injections
@@ -52,23 +56,17 @@ local kern_code = nodecodes.kern
local dir_code = nodecodes.dir
local localpar_code = nodecodes.localpar
-local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
-
local getfield = nuts.getfield
local getnext = nuts.getnext
local getprev = nuts.getprev
local getid = nuts.getid
local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
-local getchar = nuts.getchar
local getlist = nuts.getlist
local getdisc = nuts.getdisc
-local getcomponents = nuts.getcomponents
local isglyph = nuts.isglyph
local getkern = nuts.getkern
-local getdir = nuts.getdir
+local getdirection = nuts.getdirection
local getwidth = nuts.getwidth
local setbox = nuts.setbox
@@ -78,10 +76,11 @@ local setsubtype = nuts.setsubtype
local copy_node_list = nuts.copy_list
local hpack_node_list = nuts.hpack
local flush_node_list = nuts.flush_list
-local traverse_nodes = nuts.traverse
------ traverse_id = nuts.traverse_id
local protect_glyphs = nuts.protect_glyphs
+local nextnode = nuts.traversers.node
+local nextglyph = nuts.traversers.glyph
+
local nodepool = nuts.pool
local new_glyph = nodepool.glyph
@@ -98,11 +97,8 @@ local fontparameters = hashes.parameters
local properties = nodes.properties.data
--- direct.set_properties_mode(true,false)
--- direct.set_properties_mode(true,true) -- default
-
local function freeze(h,where)
- for n in traverse_nodes(tonut(h)) do -- todo: disc but not traced anyway
+ for n in nextnode, h do -- todo: disc but not traced anyway
local p = properties[n]
if p then
local i = p.injections if i then p.injections = fastcopy(i) end
@@ -115,15 +111,15 @@ local function freeze(h,where)
end
function char_tracers.collect(head,list,tag,n)
- head = tonut(head)
n = n or 0
- local ok, fn = false, nil
+ local ok = false
+ local fn = nil
while head do
- local c, id = isglyph(head)
- if c then
- local f = getfont(head)
- if f ~= fn then
- ok, fn = false, f
+ local char, id = isglyph(head)
+ if char then
+ local font = id
+ if font ~= fn then
+ ok, fn = false, font
end
if not ok then
ok = true
@@ -132,23 +128,23 @@ function char_tracers.collect(head,list,tag,n)
list[n][tag] = { }
end
local l = list[n][tag]
- -- l[#l+1] = { c, f, i }
- l[#l+1] = { c, f }
+ -- l[#l+1] = { char, font, i }
+ l[#l+1] = { char, font }
elseif id == disc_code then
-- skip
-- local pre, post, replace = getdisc(head)
-- if replace then
- -- for n in traverse_id(glyph_code,replace) do
+ -- for n in nextglyph, replace do
-- l[#l+1] = { c, f }
-- end
-- end
-- if pre then
- -- for n in traverse_id(glyph_code,pre) do
+ -- for n in nextglyph, pre do
-- l[#l+1] = { c, f }
-- end
-- end
-- if post then
- -- for n in traverse_id(glyph_code,post) do
+ -- for n in nextglyph, post do
-- l[#l+1] = { c, f }
-- end
-- end
@@ -164,7 +160,8 @@ function char_tracers.equal(ta, tb)
return false
else
for i=1,#ta do
- local a, b = ta[i], tb[i]
+ local a = ta[i]
+ local b = tb[i]
-- if a[1] ~= b[1] or a[2] ~= b[2] or a[3] ~= b[3] then
if a[1] ~= b[1] or a[2] ~= b[2] then
return false
@@ -221,12 +218,12 @@ function char_tracers.start()
function handlers.characters(head)
local n = #list
char_tracers.collect(head,list,'before',n)
- local h, d = npc(tonode(head)) -- for the moment tonode
+ head = npc(head) -- for the moment tonode
char_tracers.collect(head,list,'after',n)
if #list > n then
list[#list+1] = { }
end
- return h, d
+ return head
end
function char_tracers.stop()
tracers.list['characters'] = list
@@ -297,47 +294,44 @@ end
function step_tracers.features()
-- we cannot use first_glyph here as it only finds characters with subtype < 256
local f = collection[1]
- while f do
- if getid(f) == glyph_code then
- local tfmdata = fontidentifiers[getfont(f)]
- local features = tfmdata.resources.features
- local result_1 = { }
- local result_2 = { }
- local gpos = features and features.gpos or { }
- local gsub = features and features.gsub or { }
- for feature, value in table.sortedhash(tfmdata.shared.features) do
- if feature == "number" or feature == "features" then
- value = false
- elseif type(value) == "boolean" then
- if value then
- value = "yes"
- else
- value = false
- end
- else
- -- use value
- end
+ for n, char, font in nextglyph, f do
+ local tfmdata = fontidentifiers[font]
+ local features = tfmdata.resources.features
+ local result_1 = { }
+ local result_2 = { }
+ local gpos = features and features.gpos or { }
+ local gsub = features and features.gsub or { }
+ for feature, value in table.sortedhash(tfmdata.shared.features) do
+ if feature == "number" or feature == "features" then
+ value = false
+ elseif type(value) == "boolean" then
if value then
- if gpos[feature] or gsub[feature] or feature == "language" or feature == "script" then
- result_1[#result_1+1] = formatters["%s=%s"](feature,value)
- else
- result_2[#result_2+1] = formatters["%s=%s"](feature,value)
- end
+ value = "yes"
+ else
+ value = false
end
- end
- if #result_1 > 0 then
- context("{\\bf[basic:} %, t{\\bf]} ",result_1)
else
- context("{\\bf[}no basic features{\\bf]} ")
+ -- use value
end
- if #result_2 > 0 then
- context("{\\bf[extra:} %, t{\\bf]}",result_2)
- else
- context("{\\bf[}no extra features{\\bf]}")
+ if value then
+ if gpos[feature] or gsub[feature] or feature == "language" or feature == "script" then
+ result_1[#result_1+1] = formatters["%s=%s"](feature,value)
+ else
+ result_2[#result_2+1] = formatters["%s=%s"](feature,value)
+ end
end
- return
end
- f = getnext(f)
+ if #result_1 > 0 then
+ context("{\\bf[basic:} %, t{\\bf]} ",result_1)
+ else
+ context("{\\bf[}no basic features{\\bf]} ")
+ end
+ if #result_2 > 0 then
+ context("{\\bf[extra:} %, t{\\bf]}",result_2)
+ else
+ context("{\\bf[}no extra features{\\bf]}")
+ end
+ return
end
end
@@ -349,21 +343,15 @@ end
function step_tracers.font(command)
local c = collection[1]
- while c do
- local id = getid(c)
- if id == glyph_code then
- local font = getfont(c)
- local name = file.basename(fontproperties[font].filename or "unknown")
- local size = fontparameters[font].size or 0
- if command then
- context[command](font,name,size) -- size in sp
- else
- context("[%s: %s @ %p]",font,name,size)
- end
- return
+ for n, char, font in nextglyph, c do
+ local name = file.basename(fontproperties[font].filename or "unknown")
+ local size = fontparameters[font].size or 0
+ if command then
+ context[command](font,name,size) -- size in sp
else
- c = getnext(c)
+ context("[%s: %s @ %p]",font,name,size)
end
+ return
end
end
@@ -376,9 +364,7 @@ local colors = {
function step_tracers.codes(i,command,space)
local c = collection[i]
- local function showchar(c)
- local f = getfont(c)
- local c = getchar(c)
+ local function showchar(c,f)
if command then
local d = fontdescriptions[f]
local d = d and d[c]
@@ -392,10 +378,10 @@ function step_tracers.codes(i,command,space)
if w then
context.startcolor(colors[what])
context("%s:",what)
- for c in traverse_nodes(w) do
- local id = getid(c)
+ for c, id in nextnode, w do
if id == glyph_code then
- showchar(c)
+ local c, f = isglyph(c)
+ showchar(c,f)
else
context("[%s]",nodecodes[id])
end
@@ -406,11 +392,11 @@ function step_tracers.codes(i,command,space)
end
while c do
- local id = getid(c)
- if id == glyph_code then
- showchar(c)
- elseif id == dir_code or id == localpar_code then
- context("[%s]",getdir(c))
+ local char, id = isglyph(c)
+ if char then
+ showchar(char,id)
+ elseif id == dir_code or (id == localpar_code and getsubtype(c) == 0) then
+ context("[%s]",getdirection(c) or "?")
elseif id == disc_code then
local pre, post, replace = getdisc(c)
if pre or post or replace then
@@ -453,13 +439,12 @@ end
function step_tracers.check(head)
if collecting then
step_tracers.reset()
- local h = tonut(head)
- local n = copy_node_list(h)
+ local n = copy_node_list(head)
freeze(n,"check")
- injections.keepcounts(n) -- one-time
+ injections.keepcounts() -- one-time
local l = injections.handler(n,"trace")
if l then -- hm, can be false
- n = tonut(l)
+ n = l
end
protect_glyphs(n)
collection[1] = n
@@ -470,13 +455,12 @@ function step_tracers.register(head)
if collecting then
local nc = #collection+1
if messages[nc] then
- local h = tonut(head)
- local n = copy_node_list(h)
+ local n = copy_node_list(head)
freeze(n,"register")
- injections.keepcounts(n) -- one-time
+ injections.keepcounts() -- one-time
local l = injections.handler(n,"trace")
if l then -- hm, can be false
- n = tonut(l)
+ n = l
end
protect_glyphs(n)
collection[nc] = n
@@ -501,14 +485,11 @@ local threshold = 65536 -- 1pt
local function toutf(list,result,nofresult,stopcriterium,nostrip)
if list then
- for n in traverse_nodes(tonut(list)) do
- local c, id = isglyph(n)
- if c then
- local components = getcomponents(n)
- if components then
- result, nofresult = toutf(components,result,nofresult,false,true)
- elseif c > 0 then
- local fc = fontcharacters[getfont(n)]
+ for n, id in nextnode, tonut(list) do
+ if id == glyph_code then
+ local c, f = isglyph(n)
+ if c > 0 then
+ local fc = fontcharacters[f]
if fc then
local fcc = fc[c]
if fcc then
diff --git a/tex/context/base/mkiv/font-ocl.lua b/tex/context/base/mkiv/font-ocl.lua
index b17cf991d..0976cdb21 100644
--- a/tex/context/base/mkiv/font-ocl.lua
+++ b/tex/context/base/mkiv/font-ocl.lua
@@ -13,13 +13,20 @@ local round, max = math.round, math.round
local sortedkeys, sortedhash = table.sortedkeys, table.sortedhash
local setmetatableindex = table.setmetatableindex
-local formatters = string.formatters
-local tounicode = fonts.mappings.tounicode
+local formatters = string.formatters
+local tounicode = fonts.mappings.tounicode
-local otf = fonts.handlers.otf
+local helpers = fonts.helpers
-local f_color = formatters["%.3f %.3f %.3f rg"]
-local f_gray = formatters["%.3f g"]
+local charcommand = helpers.commands.char
+local rightcommand = helpers.commands.right
+local leftcommand = helpers.commands.left
+local downcommand = helpers.commands.down
+
+local otf = fonts.handlers.otf
+
+local f_color = formatters["%.3f %.3f %.3f rg"]
+local f_gray = formatters["%.3f g"]
if context then
@@ -56,31 +63,41 @@ end)
if context then
+ -- \definefontcolorpalette [emoji-r] [emoji-red,emoji-gray,textcolor] -- looks bad
+ -- \definefontcolorpalette [emoji-r] [emoji-red,emoji-gray] -- looks okay
+
local colors = attributes.list[attributes.private('color')] or { }
local transparencies = attributes.list[attributes.private('transparency')] or { }
function otf.registerpalette(name,values)
sharedpalettes[name] = values
+ local color = lpdf.color
+ local transparency = lpdf.transparency
+ local register = colors.register
for i=1,#values do
local v = values[i]
- local c = nil
- local t = nil
- if type(v) == "table" then
- c = colors.register(name,"rgb",
- max(round((v.r or 0)*255),255)/255,
- max(round((v.g or 0)*255),255)/255,
- max(round((v.b or 0)*255),255)/255
- )
+ if v == "textcolor" then
+ values[i] = false
else
- c = colors[v]
- t = transparencies[v]
- end
- if c and t then
- values[i] = hash[lpdf.color(1,c) .. " " .. lpdf.transparency(t)]
- elseif c then
- values[i] = hash[lpdf.color(1,c)]
- elseif t then
- values[i] = hash[lpdf.color(1,t)]
+ local c = nil
+ local t = nil
+ if type(v) == "table" then
+ c = register(name,"rgb",
+ max(round((v.r or 0)*255),255)/255,
+ max(round((v.g or 0)*255),255)/255,
+ max(round((v.b or 0)*255),255)/255
+ )
+ else
+ c = colors[v]
+ t = transparencies[v]
+ end
+ if c and t then
+ values[i] = hash[color(1,c) .. " " .. transparency(t)]
+ elseif c then
+ values[i] = hash[color(1,c)]
+ elseif t then
+ values[i] = hash[color(1,t)]
+ end
end
end
end
@@ -91,11 +108,13 @@ else -- for generic
sharedpalettes[name] = values
for i=1,#values do
local v = values[i]
- values[i] = hash[f_color(
- max(round((v.r or 0)*255),255)/255,
- max(round((v.g or 0)*255),255)/255,
- max(round((v.b or 0)*255),255)/255
- )]
+ if v then
+ values[i] = hash[f_color(
+ max(round((v.r or 0)*255),255)/255,
+ max(round((v.g or 0)*255),255)/255,
+ max(round((v.b or 0)*255),255)/255
+ )]
+ end
end
end
@@ -127,16 +146,11 @@ local start = { "pdf", "mode", "font" } -- force text mode (so get q Q right)
local push = { "pdf", "page", "q" }
local pop = { "pdf", "page", "Q" }
-if not LUATEXFUNCTIONALITY or LUATEXFUNCTIONALITY < 6472 then
- start = { "nop" }
- ----- = stop
-end
-
-- -- This one results in color directives inside BT ET but has less q Q pairs. It
-- -- only shows the first glyph in acrobat and nothing more. No problem with other
-- -- renderers.
--
--- local function initializecolr(tfmdata,kind,value) -- hm, always value
+-- local function initialize(tfmdata,kind,value) -- hm, always value
-- if value then
-- local resources = tfmdata.resources
-- local palettes = resources.colorpalettes
@@ -161,11 +175,6 @@ end
-- tfmdata.fonts = {
-- { id = 0 }
-- }
--- local widths = setmetatableindex(function(t,k)
--- local v = { "right", -k }
--- t[k] = v
--- return v
--- end)
-- --
-- local getactualtext = otf.getactualtext
-- local default = colorvalues[#colorvalues]
@@ -173,12 +182,6 @@ end
-- local actualb = { "pdf", "page", b } -- saves tables
-- local actuale = { "pdf", "page", e } -- saves tables
-- --
--- local cache = setmetatableindex(function(t,k)
--- local v = { "char", k } -- could he a weak shared hash
--- t[k] = v
--- return v
--- end)
--- --
-- for unicode, character in next, characters do
-- local description = descriptions[unicode]
-- if description then
@@ -187,7 +190,7 @@ end
-- local u = description.unicode or characters[unicode].unicode
-- local w = character.width or 0
-- local s = #colorlist
--- local goback = w ~= 0 and widths[w] or nil -- needs checking: are widths the same
+-- local goback = w ~= 0 and leftcommand[w] or nil -- needs checking: are widths the same
-- local t = {
-- start,
-- not u and actualb or { "pdf", "page", (getactualtext(tounicode(u))) }
@@ -202,7 +205,7 @@ end
-- n = n + 1 t[n] = v
-- l = v
-- end
--- n = n + 1 t[n] = cache[entry.slot]
+-- n = n + 1 t[n] = charcommand[entry.slot]
-- if s > 1 and i < s and goback then
-- n = n + 1 t[n] = goback
-- end
@@ -221,7 +224,7 @@ end
-- -- Here we have no color change in BT .. ET and more q Q pairs but even then acrobat
-- -- fails displaying the overlays correctly. Other renderers do it right.
-local function initializecolr(tfmdata,kind,value) -- hm, always value
+local function initialize(tfmdata,kind,value)
if value then
local resources = tfmdata.resources
local palettes = resources.colorpalettes
@@ -232,8 +235,14 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value
converted = setmetatableindex(convert)
resources.converted = converted
end
- local colorvalues = sharedpalettes[value] or converted[palettes[tonumber(value) or 1] or palettes[1]] or { }
- local classes = #colorvalues
+ local colorvalues = sharedpalettes[value]
+ local default = false -- so the text color (bad for icon overloads)
+ if colorvalues then
+ default = colorvalues[#colorvalues]
+ else
+ colorvalues = converted[palettes[tonumber(value) or 1] or palettes[1]] or { }
+ end
+ local classes = #colorvalues
if classes == 0 then
return
end
@@ -246,24 +255,12 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value
tfmdata.fonts = {
{ id = 0 }
}
- local widths = setmetatableindex(function(t,k)
- local v = { "right", -k }
- t[k] = v
- return v
- end)
--
local getactualtext = otf.getactualtext
- local default = colorvalues[#colorvalues]
local b, e = getactualtext(tounicode(0xFFFD))
local actualb = { "pdf", "page", b } -- saves tables
local actuale = { "pdf", "page", e } -- saves tables
--
- local cache = setmetatableindex(function(t,k)
- local v = { "char", k } -- could he a weak shared hash
- t[k] = v
- return v
- end)
- --
for unicode, character in next, characters do
local description = descriptions[unicode]
if description then
@@ -272,7 +269,7 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value
local u = description.unicode or characters[unicode].unicode
local w = character.width or 0
local s = #colorlist
- local goback = w ~= 0 and widths[w] or nil -- needs checking: are widths the same
+ local goback = w ~= 0 and leftcommand[w] or nil -- needs checking: are widths the same
local t = {
start, -- really needed
not u and actualb or { "pdf", "page", (getactualtext(tounicode(u))) }
@@ -291,8 +288,14 @@ local function initializecolr(tfmdata,kind,value) -- hm, always value
f = true
n = n + 1 t[n] = v
l = v
+ else
+ if f then
+ n = n + 1 t[n] = pop
+ end
+ f = false
+ l = nil
end
- n = n + 1 t[n] = cache[entry.slot]
+ n = n + 1 t[n] = charcommand[entry.slot]
if s > 1 and i < s and goback then
n = n + 1 t[n] = goback
end
@@ -314,80 +317,60 @@ fonts.handlers.otf.features.register {
name = "colr",
description = "color glyphs",
manipulators = {
- base = initializecolr,
- node = initializecolr,
+ base = initialize,
+ node = initialize,
}
}
do
- -- local f_setstream = formatters[ [[io.savedata("svg-glyph-%05i",%q)]] ]
- -- local f_getstream = formatters[ [[svg-glyph-%05i]] ]
-
- -- function otfsvg.storepdfdata(pdf)
- -- nofstreams = nofstreams + 1
- -- storepdfdata = function(pdf)
- -- nofstreams = nofstreams + 1
- -- return f_setstream(nofstreams,pdf), f_getstream(nofstreams)
- -- end
- -- end
-
local nofstreams = 0
local f_name = formatters[ [[pdf-glyph-%05i]] ]
local f_used = context and formatters[ [[original:///%s]] ] or formatters[ [[%s]] ]
local hashed = { }
local cache = { }
- function otf.storepdfdata(pdf)
- local done = hashed[pdf]
- if not done then
- nofstreams = nofstreams + 1
- local o, n = epdf.openMemStream(pdf,#pdf,f_name(nofstreams))
- cache[n] = o -- we need to keep in mem
- done = f_used(n)
- hashed[pdf] = done
+ if epdf then
+
+ local openpdf = epdf.openMemStream
+
+ function otf.storepdfdata(pdf)
+ local done = hashed[pdf]
+ if not done then
+ nofstreams = nofstreams + 1
+ local o, n = openpdf(pdf,#pdf,f_name(nofstreams))
+ cache[n] = o -- we need to keep in mem
+ done = f_used(n)
+ hashed[pdf] = done
+ end
+ return done
+ end
+
+ else
+
+ local openpdf = pdfe.new
+ ----- prefix = "data:application/pdf,"
+
+ function otf.storepdfdata(pdf)
+ local done = hashed[pdf]
+ if not done then
+ nofstreams = nofstreams + 1
+ local f = f_name(nofstreams)
+ local n = openpdf(pdf,#pdf,f)
+ done = f_used(n)
+ hashed[pdf] = done
+ end
+ return done
end
- return nil, done, nil
- end
- -- maybe more efficient but much slower (and we hash already)
- --
- -- if context then
- --
- -- local storepdfdata = otf.storepdfdata
- -- local initialized = false
- --
- -- function otf.storepdfdata(pdf)
- -- if not initialized then
- -- if resolvers.setmemstream then
- -- local f_setstream = formatters[ [[resolvers.setmemstream("pdf-glyph-%05i",%q,true)]] ]
- -- local f_getstream = formatters[ [[memstream:///pdf-glyph-%05i]] ]
- -- local f_nilstream = formatters[ [[resolvers.resetmemstream("pdf-glyph-%05i",true)]] ]
- -- storepdfdata = function(pdf)
- -- local done = hashed[pdf]
- -- local set = nil
- -- local reset = nil
- -- if not done then
- -- nofstreams = nofstreams + 1
- -- set = f_setstream(nofstreams,pdf)
- -- done = f_getstream(nofstreams)
- -- reset = f_nilstream(nofstreams)
- -- hashed[pdf] = done
- -- end
- -- return set, done, reset
- -- end
- -- otf.storepdfdata = storepdfdata
- -- end
- -- initialized = true
- -- end
- -- return storepdfdata(pdf)
- -- end
- --
- -- end
+ end
end
-local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = sbix|svg
+-- I'll probably make a variant for context as we can do it more efficient there than in
+-- generic.
+
+local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = png|svg
if not tfmdata or not pdfshapes or not kind then
return
end
@@ -400,7 +383,7 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = sbix|svg
properties.virtualized = true
--
tfmdata.fonts = {
- { id = 0 }
+ { id = 0 } -- not really needed
}
--
local getactualtext = otf.getactualtext
@@ -410,6 +393,12 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = sbix|svg
local actualb = { "pdf", "page", b } -- saves tables
local actuale = { "pdf", "page", e } -- saves tables
--
+ local vfimage = lpdf and lpdf.vfimage or function(wd,ht,dp,data,name)
+ -- needed for generic (if used there at all)
+ local name = storepdfdata(data)
+ return { "image", { filename = name, width = wd, height = ht, depth = dp } }
+ end
+ --
for unicode, character in sortedhash(characters) do -- sort is nicer for svg
local index = character.index
if index then
@@ -428,31 +417,30 @@ local function pdftovirtual(tfmdata,pdfshapes,kind) -- kind = sbix|svg
dy = 0
end
if data then
- local setcode, name, nilcode = storepdfdata(data)
- if name then
- local bt = unicode and getactualtext(unicode)
- local wd = character.width or 0
- local ht = character.height or 0
- local dp = character.depth or 0
- character.commands = {
- not unicode and actualb or { "pdf", "page", (getactualtext(unicode)) },
- { "down", dp + dy * hfactor },
- { "right", dx * hfactor },
- -- setcode and { "lua", setcode } or nop,
- { "image", { filename = name, width = wd, height = ht, depth = dp } },
- -- nilcode and { "lua", nilcode } or nop,
- actuale,
- }
- character[kind] = true
- end
+ -- We can delay storage by a lua function in commands: but then we need to
+ -- be able to provide our own mem stream name (so that we can reserve it).
+ -- Anyway, we will do this different in a future version of context.
+ local bt = unicode and getactualtext(unicode)
+ local wd = character.width or 0
+ local ht = character.height or 0
+ local dp = character.depth or 0
+ -- The down and right will change too (we can move that elsewhere).
+ character.commands = {
+ not unicode and actualb or { "pdf", "page", (getactualtext(unicode)) },
+ downcommand[dp + dy * hfactor],
+ rightcommand[dx * hfactor],
+ vfimage(wd,ht,dp,data,name),
+ actuale,
+ }
+ character[kind] = true
end
end
end
end
local otfsvg = otf.svg or { }
-otf.svg = otfsvg
-otf.svgenabled = true
+otf.svg = otfsvg
+otf.svgenabled = true
do
@@ -583,27 +571,27 @@ fonts.handlers.otf.features.register {
-- This can be done differently e.g. with ffi and gm and we can share code anway. Using
-- batchmode in gm is not faster and as it accumulates we would need to flush all
--- individual shapes.
+-- individual shapes. But ... in context lmtx (and maybe the backport) we will use
+-- a different and more efficient method anyway. I'm still wondering if I should
+-- keep color code in generic. Maybe it should be optional.
-local otfsbix = otf.sbix or { }
-otf.sbix = otfsbix
-otf.sbixenabled = true
+local otfpng = otf.png or { }
+otf.png = otfpng
+otf.pngenabled = true
do
- -- for now png but also other bitmap formats
-
- local report_sbix = logs.reporter("fonts","sbix conversion")
+ local report_png = logs.reporter("fonts","png conversion")
local loaddata = io.loaddata
local savedata = io.savedata
local remove = os.remove
local runner = sandbox and sandbox.registerrunner {
- name = "otfsbix",
+ name = "otfpng",
program = "gm",
- template = "convert -quality 100 temp-otf-sbix-shape.sbix temp-otf-sbix-shape.pdf > temp-otf-svg-shape.log",
- -- reporter = report_sbix,
+ template = "convert -quality 100 temp-otf-png-shape.png temp-otf-png-shape.pdf > temp-otf-svg-shape.log",
+ -- reporter = report_png,
}
if not runner then
@@ -611,29 +599,29 @@ do
-- poor mans variant for generic:
--
runner = function()
- return os.execute("gm convert -quality 100 temp-otf-sbix-shape.sbix temp-otf-sbix-shape.pdf > temp-otf-svg-shape.log")
+ return os.execute("gm convert -quality 100 temp-otf-png-shape.png temp-otf-png-shape.pdf > temp-otf-svg-shape.log")
end
end
-- Alternatively we can create a single pdf file with -adjoin and then pick up pages from
-- that file but creating thousands of small files is no fun either.
- function otfsbix.topdf(sbixshapes)
+ function otfpng.topdf(pngshapes)
local pdfshapes = { }
- local sbixfile = "temp-otf-sbix-shape.sbix"
- local pdffile = "temp-otf-sbix-shape.pdf"
+ local pngfile = "temp-otf-png-shape.png"
+ local pdffile = "temp-otf-png-shape.pdf"
local nofdone = 0
- local indices = sortedkeys(sbixshapes) -- can be sparse
+ local indices = sortedkeys(pngshapes) -- can be sparse
local nofindices = #indices
- report_sbix("processing %i sbix containers",nofindices)
+ report_png("processing %i png containers",nofindices)
statistics.starttiming()
for i=1,nofindices do
local index = indices[i]
- local entry = sbixshapes[index]
- local data = entry.data
+ local entry = pngshapes[index]
+ local data = entry.data -- or placeholder
local x = entry.x
local y = entry.y
- savedata(sbixfile,data)
+ savedata(pngfile,data)
runner()
pdfshapes[index] = {
x = x ~= 0 and x or nil,
@@ -642,43 +630,44 @@ do
}
nofdone = nofdone + 1
if nofdone % 100 == 0 then
- report_sbix("%i shapes processed",nofdone)
+ report_png("%i shapes processed",nofdone)
end
end
- report_sbix("processing %i pdf results",nofindices)
- remove(sbixfile)
+ report_png("processing %i pdf results",nofindices)
+ remove(pngfile)
remove(pdffile)
statistics.stoptiming()
if statistics.elapsedseconds then
- report_sbix("sbix conversion time %s",statistics.elapsedseconds() or "-")
+ report_png("png conversion time %s",statistics.elapsedseconds() or "-")
end
return pdfshapes
- -- end
end
end
-local function initializesbix(tfmdata,kind,value) -- hm, always value
- if value and otf.sbixenabled then
- local sbix = tfmdata.properties.sbix
- local hash = sbix and sbix.hash
- local timestamp = sbix and sbix.timestamp
+-- This will change in a future version of context. More direct.
+
+local function initializepng(tfmdata,kind,value) -- hm, always value
+ if value and otf.pngenabled then
+ local png = tfmdata.properties.png
+ local hash = png and png.hash
+ local timestamp = png and png.timestamp
if not hash then
return
end
local pdffile = containers.read(otf.pdfcache,hash)
local pdfshapes = pdffile and pdffile.pdfshapes
if not pdfshapes or pdffile.timestamp ~= timestamp then
- local sbixfile = containers.read(otf.sbixcache,hash)
- local sbixshapes = sbixfile and sbixfile.sbixshapes
- pdfshapes = sbixshapes and otfsbix.topdf(sbixshapes) or { }
+ local pngfile = containers.read(otf.pngcache,hash)
+ local pngshapes = pngfile and pngfile.pngshapes
+ pdfshapes = pngshapes and otfpng.topdf(pngshapes) or { }
containers.write(otf.pdfcache, hash, {
pdfshapes = pdfshapes,
timestamp = timestamp,
})
end
--
- pdftovirtual(tfmdata,pdfshapes,"sbix")
+ pdftovirtual(tfmdata,pdfshapes,"png")
end
end
@@ -686,8 +675,16 @@ fonts.handlers.otf.features.register {
name = "sbix",
description = "sbix glyphs",
manipulators = {
- base = initializesbix,
- node = initializesbix,
+ base = initializepng,
+ node = initializepng,
}
}
+fonts.handlers.otf.features.register {
+ name = "cblc",
+ description = "cblc glyphs",
+ manipulators = {
+ base = initializepng,
+ node = initializepng,
+ }
+}
diff --git a/tex/context/base/mkiv/font-one.lua b/tex/context/base/mkiv/font-one.lua
index a3dc7b038..18ba51185 100644
--- a/tex/context/base/mkiv/font-one.lua
+++ b/tex/context/base/mkiv/font-one.lua
@@ -86,14 +86,16 @@ function afm.load(filename)
local name = file.removesuffix(file.basename(filename))
local data = containers.read(afm.cache,name)
local attr = lfs.attributes(filename)
- local size, time = attr.size or 0, attr.modification or 0
+ local size = attr and attr.size or 0
+ local time = attr and attr.modification or 0
--
local pfbfile = file.replacesuffix(name,"pfb")
local pfbname = resolvers.findfile(pfbfile,"pfb") or ""
if pfbname == "" then
pfbname = resolvers.findfile(file.basename(pfbfile),"pfb") or ""
end
- local pfbsize, pfbtime = 0, 0
+ local pfbsize = 0
+ local pfbtime = 0
if pfbname ~= "" then
local attr = lfs.attributes(pfbname)
pfbsize = attr.size or 0
@@ -106,6 +108,7 @@ function afm.load(filename)
afmenhancers.apply(data,filename)
-- otfreaders.addunicodetable(data) -- only when not done yet
fonts.mappings.addtounicode(data,filename)
+ otfreaders.stripredundant(data)
-- otfreaders.extend(data)
otfreaders.pack(data)
data.size = size
@@ -323,7 +326,8 @@ local addthem = function(rawdata,ligatures)
local one = descriptions[unicodes[ligname]]
if one then
for _, pair in next, ligdata do
- local two, three = unicodes[pair[1]], unicodes[pair[2]]
+ local two = unicodes[pair[1]]
+ local three = unicodes[pair[2]]
if two and three then
local ol = one.ligatures
if ol then
@@ -391,7 +395,7 @@ local function enhance_add_extra_kerns(rawdata) -- using shcodes is not robust h
if what then
for complex, simple in next, what do
complex = unicodes[complex]
- simple = unicodes[simple]
+ simple = unicodes[simple]
if complex and simple then
local complexdescription = descriptions[complex]
if complexdescription then -- optional
@@ -444,7 +448,8 @@ local function adddimensions(data) -- we need to normalize afm to otf i.e. index
for unicode, description in next, data.descriptions do
local bb = description.boundingbox
if bb then
- local ht, dp = bb[4], -bb[2]
+ local ht = bb[4]
+ local dp = -bb[2]
if ht == 0 or ht < 0 then
-- no need to set it and no negative heights, nil == 0
else
diff --git a/tex/context/base/mkiv/font-onr.lua b/tex/context/base/mkiv/font-onr.lua
index 26a782649..8523d8729 100644
--- a/tex/context/base/mkiv/font-onr.lua
+++ b/tex/context/base/mkiv/font-onr.lua
@@ -26,7 +26,7 @@ local match, lower, gsub, strip, find = string.match, string.lower, string.gsub,
local char, byte, sub = string.char, string.byte, string.sub
local abs = math.abs
local bxor, rshift = bit32.bxor, bit32.rshift
-local P, S, R, Cmt, C, Ct, Cs, Carg, Cf, Cg = lpeg.P, lpeg.S, lpeg.R, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cf, lpeg.Cg
+local P, S, R, V, Cmt, C, Ct, Cs, Carg, Cf, Cg, Cc = lpeg.P, lpeg.S, lpeg.R, lpeg.V, lpeg.Cmt, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg, lpeg.Cf, lpeg.Cg, lpeg.Cc
local lpegmatch, patterns = lpeg.match, lpeg.patterns
local trace_indexing = false trackers.register("afm.indexing", function(v) trace_indexing = v end)
@@ -83,31 +83,40 @@ do
end
- local charstrings = P("/CharStrings")
- local subroutines = P("/Subrs")
- local encoding = P("/Encoding")
- local dup = P("dup")
- local put = P("put")
- local array = P("array")
- local name = P("/") * C((R("az","AZ","09")+S("-_."))^1)
- local digits = R("09")^1
- local cardinal = digits / tonumber
- local spaces = P(" ")^1
- local spacing = patterns.whitespace^0
+ local charstrings = P("/CharStrings")
+ local subroutines = P("/Subrs")
+ local encoding = P("/Encoding")
+ local dup = P("dup")
+ local put = P("put")
+ local array = P("array")
+ local name = P("/") * C((R("az","AZ","09")+S("-_."))^1)
+ local digits = R("09")^1
+ local cardinal = digits / tonumber
+ local spaces = P(" ")^1
+ local spacing = patterns.whitespace^0
local routines, vector, chars, n, m
local initialize = function(str,position,size)
n = 0
- m = size -- % tonumber(size)
+ m = size
return position + 1
end
local setroutine = function(str,position,index,size,filename)
- local forward = position + tonumber(size)
+ if routines[index] then
+ -- we have passed the end
+ return false
+ end
+ local forward = position + size
local stream = decrypt(sub(str,position+1,forward),4330,4)
routines[index] = { byte(stream,1,#stream) }
- return forward
+ n = n + 1
+ if n >= m then
+ -- m should be index now but can we assume ordering?
+ return #str
+ end
+ return forward + 1
end
local setvector = function(str,position,name,size,filename)
@@ -152,7 +161,7 @@ do
local p_filterroutines = -- dup <i> <n> RD or -| <n encrypted bytes> NP or |
(1-subroutines)^0 * subroutines * spaces * Cmt(cardinal,initialize)
- * (Cmt(cardinal * spaces * cardinal * p_rd * Carg(1), setroutine) * p_np + P(1))^1
+ * (Cmt(cardinal * spaces * cardinal * p_rd * Carg(1), setroutine) * p_np + (1-p_nd))^1
local p_filtershapes = -- /foo <n> RD <n encrypted bytes> ND
(1-charstrings)^0 * charstrings * spaces * Cmt(cardinal,initialize)
@@ -175,7 +184,33 @@ do
-- if one of first 4 not 0-9A-F then binary else hex
- local function loadpfbvector(filename,shapestoo)
+ local key = spacing * P("/") * R("az","AZ")
+ local str = spacing * Cs { (P("(")/"") * ((1 - P("\\(") - P("\\)") - S("()")) + V(1))^0 * (P(")")/"") }
+ local num = spacing * (R("09") + S("+-."))^1 / tonumber
+ local arr = spacing * Ct (S("[{") * (num)^0 * spacing * S("]}"))
+ local boo = spacing * (P("true") * Cc(true) + P("false") * Cc(false))
+ local nam = spacing * P("/") * Cs(R("az","AZ")^1)
+
+ local p_filtermetadata = (
+ P("/") * Carg(1) * ( (
+ C("version") * str
+ + C("Copyright") * str
+ + C("Notice") * str
+ + C("FullName") * str
+ + C("FamilyName") * str
+ + C("Weight") * str
+ + C("ItalicAngle") * num
+ + C("isFixedPitch") * boo
+ + C("UnderlinePosition") * num
+ + C("UnderlineThickness") * num
+ + C("FontName") * nam
+ + C("FontMatrix") * arr
+ + C("FontBBox") * arr
+ ) ) / function(t,k,v) t[lower(k)] = v end
+ + P(1)
+ )^0 * Carg(1)
+
+ local function loadpfbvector(filename,shapestoo,streams)
-- for the moment limited to encoding only
local data = io.loaddata(resolvers.findfile(filename))
@@ -200,11 +235,14 @@ do
binary = decrypt(binary,55665,4)
local names = { }
+
local encoding = lpegmatch(p_filterencoding,ascii)
+ local metadata = lpegmatch(p_filtermetadata,ascii,1,{})
local glyphs = { }
routines, vector, chars = { }, { }, { }
- if shapestoo then
+ if shapestoo or streams then
+ -- io.savedata("foo.txt",binary)
lpegmatch(p_filterroutines,binary,1,filename)
lpegmatch(p_filtershapes,binary,1,filename)
local data = {
@@ -216,7 +254,8 @@ do
}
},
}
- fonts.handlers.otf.readers.parsecharstrings(false,data,glyphs,true,true)
+ -- only cff 1 in type 1 fonts
+ fonts.handlers.otf.readers.parsecharstrings(false,data,glyphs,true,"cff",streams)
else
lpegmatch(p_filternames,binary,1,filename)
end
@@ -225,7 +264,7 @@ do
routines, vector, chars = nil, nil, nil
- return names, encoding, glyphs
+ return names, encoding, glyphs, metadata
end
diff --git a/tex/context/base/mkiv/font-osd.lua b/tex/context/base/mkiv/font-osd.lua
index 9f99fd57f..32d791b48 100644
--- a/tex/context/base/mkiv/font-osd.lua
+++ b/tex/context/base/mkiv/font-osd.lua
@@ -6,6 +6,9 @@ if not modules then modules = { } end modules ['font-osd'] = { -- script devanag
license = "see context related readme files"
}
+
+-- we need to check nbsphash (context only)
+
-- A few remarks:
--
-- This code is a partial rewrite of the code that deals with devanagari. The data
@@ -96,8 +99,6 @@ local otffeatures = fonts.constructors.features.otf
local registerotffeature = otffeatures.register
local nuts = nodes.nuts
-local tonode = nuts.tonode
-local tonut = nuts.tonut
local getnext = nuts.getnext
local getprev = nuts.getprev
@@ -152,47 +153,27 @@ replace_all_nbsp = function(head) -- delayed definition
return replace_all_nbsp(head)
end
-local xprocesscharacters = nil
+local processcharacters = nil
if context then
- xprocesscharacters = function(head,font)
- xprocesscharacters = nodes.handlers.characters
- return xprocesscharacters(head,font)
+ local fontprocesses = fonts.hashes.processes
+ function processcharacters(head,font)
+ local processors = fontprocesses[font]
+ for i=1,#processors do
+ head = processors[i](head,font,0)
+ end
+ return head
end
else
- xprocesscharacters = function(head,font)
- xprocesscharacters = nodes.handlers.nodepass -- generic
- return xprocesscharacters(head,font)
+ function processcharacters(head,font)
+ local processors = fontdata[font].shared.processes
+ for i=1,#processors do
+ head = processors[i](head,font,0)
+ end
+ return head
end
end
-local function processcharacters(head,font)
- return tonut(xprocesscharacters(tonode(head))) -- can be more efficient in context, just direct call
-end
-
--- to be tested:
---
--- local processcharacters = nil
---
--- if context then
--- local fontprocesses = fonts.hashes.processes
--- function processcharacters(head,font)
--- local processors = fontprocesses[font]
--- for i=1,#processors do
--- head = processors[i](head,font,0)
--- end
--- return head, true
--- end
--- else
--- function processcharacters(head,font)
--- local processors = fontdata[font].shared.processes
--- for i=1,#processors do
--- head = processors[i](head,font,0)
--- end
--- return head, true
--- end
--- end
-
-- We can assume that script are not mixed in the source but if that is the case
-- we might need to have consonants etc per script and initialize a local table
-- pointing to the right one. But not now.
@@ -293,10 +274,6 @@ if not indicgroups and characters then
characters.indicgroups = indicgroups
-else
-
- indicgroups = table.setmetatableindex("table")
-
end
local consonant = indicgroups.consonant
@@ -422,19 +399,19 @@ local sequence_remove_joiners = {
-- as it might depends on the font. Not that it's a bottleneck.
local basic_shaping_forms = {
- init = true, -- new
- abvs = true, -- new
+ -- init = true, -- new
+ -- abvs = true, -- new
akhn = true,
blwf = true,
- calt = true, -- new
+ -- calt = true, -- new
cjct = true,
half = true,
- haln = true, -- new
+ -- haln = true, -- new
nukt = true,
pref = true,
- pres = true, -- new
+ -- pres = true, -- new
pstf = true,
- psts = true, -- new
+ -- psts = true, -- new
rkrf = true,
rphf = true,
vatu = true,
@@ -605,9 +582,7 @@ local function initializedevanagi(tfmdata)
end
end
end
-if reph then
- seqsubset[#seqsubset+1] = { kind, coverage, reph }
-end
+ seqsubset[#seqsubset+1] = { kind, coverage, reph }
end
end
end
@@ -691,6 +666,19 @@ registerotffeature {
},
}
+local show_syntax_errors = false
+
+local function inject_syntax_error(head,current,char)
+ local signal = copy_node(current)
+ copyinjection(signal,current)
+ if pre_mark[char] then
+ setchar(signal,dotted_circle)
+ else
+ setchar(current,dotted_circle)
+ end
+ return insert_node_after(head,current,signal)
+end
+
-- hm, this is applied to one character:
local function initialize_one(font,attr) -- we need a proper hook into the dataset initializer
@@ -793,10 +781,9 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
setprop(tempcurrent,a_state,unsetvalue)
if getchar(next) == getchar(tempcurrent) then
flush_list(tempcurrent)
- local n = copy_node(current)
- copyinjection(n,current) -- KE: necessary? HH: probably not as positioning comes later and we rawget/set
- setchar(current,dotted_circle)
- head = insert_node_after(head, current, n)
+ if show_syntax_errors then
+ head, current = inject_syntax_error(head,current,char)
+ end
else
setchar(current,getchar(tempcurrent)) -- we assumes that the result of blwf consists of one node
local freenode = getnext(current)
@@ -1217,7 +1204,7 @@ function handlers.devanagari_reorder_reph(head,start)
while current do
local char = ischar(current,startfont)
if char and getprop(current,a_syllabe) == startattr then
- if not c and mark_above_below_post[char] and after_subscript[char] then
+ if not c and mark_above_below_post[char] and not after_subscript[char] then
c = current
end
current = getnext(current)
@@ -1560,10 +1547,9 @@ local function reorder_two(head,start,stop,font,attr,nbspaces) -- maybe do a pas
setprop(current,a_state,unsetvalue)
if halant[getchar(current)] then
setnext(getnext(current),tmp)
- local nc = copy_node(current)
- copyinjection(nc,current)
- setchar(current,dotted_circle)
- head = insert_node_after(head,current,nc)
+ if show_syntax_errors then
+ head, current = inject_syntax_error(head,current,char)
+ end
else
setnext(current,tmp) -- assumes that result of pref, blwf, or pstf consists of one node
if changestop then
@@ -2058,24 +2044,10 @@ local function analyze_next_chars_two(c,font)
end
end
-local show_syntax_errors = false
-
-local function inject_syntax_error(head,current,char)
- local signal = copy_node(current)
- copyinjection(signal,current)
- if pre_mark[char] then
- setchar(signal,dotted_circle)
- else
- setchar(current,dotted_circle)
- end
- return insert_node_after(head,current,signal)
-end
-
-- It looks like these two analyzers were written independently but they share
-- a lot. Common code has been synced.
local function method_one(head,font,attr)
- head = tonut(head)
local current = head
local start = true
local done = false
@@ -2270,14 +2242,13 @@ local function method_one(head,font,attr)
head = replace_all_nbsp(head)
end
- return tonode(head), done
+ return head, done
end
-- there is a good change that when we run into one with subtype < 256 that the rest is also done
-- so maybe we can omit this check (it's pretty hard to get glyphs in the stream out of the blue)
local function method_two(head,font,attr)
- head = tonut(head)
local current = head
local start = true
local done = false
@@ -2366,7 +2337,7 @@ local function method_two(head,font,attr)
head = replace_all_nbsp(head)
end
- return tonode(head), done
+ return head, done
end
for i=1,nofscripts do
diff --git a/tex/context/base/mkiv/font-ota.lua b/tex/context/base/mkiv/font-ota.lua
index de626c120..76c267a81 100644
--- a/tex/context/base/mkiv/font-ota.lua
+++ b/tex/context/base/mkiv/font-ota.lua
@@ -37,12 +37,10 @@ local getprev = nuts.getprev
local getprev = nuts.getprev
local getprop = nuts.getprop
local setprop = nuts.setprop
-local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
local getchar = nuts.getchar
local ischar = nuts.is_char
-local traverse_id = nuts.traverse_id
local end_of_math = nuts.end_of_math
local nodecodes = nodes.nodecodes
@@ -112,6 +110,8 @@ analyzers.useunicodemarks = false
-- 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
+-- done can go away as can tonut
+
function analyzers.setstate(head,font)
local useunicodemarks = analyzers.useunicodemarks
local tfmdata = fontdata[font]
@@ -302,9 +302,9 @@ if not classifiers then
end
function methods.arab(head,font,attr)
- local first, last = nil, nil
- local c_first, c_last = nil, nil
- local current, done = head, false
+ local first, last, c_first, c_last
+ local current = head
+ local done = false
current = tonut(current)
while current do
local char, id = ischar(current,font)
diff --git a/tex/context/base/mkiv/font-otc.lua b/tex/context/base/mkiv/font-otc.lua
index 2bad62d60..a774a81c2 100644
--- a/tex/context/base/mkiv/font-otc.lua
+++ b/tex/context/base/mkiv/font-otc.lua
@@ -6,11 +6,10 @@ if not modules then modules = { } end modules ['font-otc'] = {
license = "see context related readme files"
}
-local format, insert, sortedkeys, tohash = string.format, table.insert, table.sortedkeys, table.tohash
-local type, next = type, next
+local insert, sortedkeys, sortedhash, tohash = table.insert, table.sortedkeys, table.sortedhash, table.tohash
+local type, next, tonumber = type, next, tonumber
local lpegmatch = lpeg.match
-local utfbyte, utflen, utfsplit = utf.byte, utf.len, utf.split
-local match = string.match
+local utfbyte, utflen = utf.byte, utf.len
local sortedhash = table.sortedhash
-- we assume that the other otf stuff is loaded already
@@ -175,6 +174,10 @@ local function addfeature(data,feature,specifications)
return
end
+ local p = lpeg.P("P")
+ * (lpeg.patterns.hexdigit^1/function(s) return tonumber(s,16) end)
+ * lpeg.P(-1)
+
local function tounicode(code)
if not code then
return
@@ -184,6 +187,7 @@ local function addfeature(data,feature,specifications)
end
local u = unicodes[code]
if u then
+ -- unicodes[code] = u
return u
end
if utflen(code) == 1 then
@@ -192,10 +196,19 @@ local function addfeature(data,feature,specifications)
return u
end
end
+ local u = lpegmatch(p,code)
+ if u then
+ -- unicodes[code] = u
+ return u
+ end
if not aglunicodes then
aglunicodes = fonts.encodings.agl.unicodes -- delayed
end
- return aglunicodes[code]
+ local u = aglunicodes[code]
+ if u then
+ -- unicodes[code] = u
+ return u
+ end
end
local coverup = otf.coverup
@@ -265,7 +278,8 @@ local function addfeature(data,feature,specifications)
if not nocheck and not description then
skip = skip + 1
elseif type(replacement) == "table" then
- local r, n = { }, 0
+ local r = { }
+ local n = 0
for i=1,#replacement do
local u = tounicode(replacement[i])
if nocheck or descriptions[u] then
@@ -467,6 +481,8 @@ local function addfeature(data,feature,specifications)
if not subtype then
subtype = lookup.type
end
+ elseif v == 0 then
+ lookups[k] = { { type = "gsub_remove" } }
else
lookups[k] = false -- { false } -- new
end
@@ -813,177 +829,6 @@ otf.enhancers.enhance = enhance
otf.enhancers.register("check extra features",enhance)
--- tlig --
-
-local tlig = { -- we need numbers for some fonts so ...
- -- endash = "hyphen hyphen",
- -- emdash = "hyphen hyphen hyphen",
- [0x2013] = { 0x002D, 0x002D },
- [0x2014] = { 0x002D, 0x002D, 0x002D },
- -- quotedblleft = "quoteleft quoteleft",
- -- quotedblright = "quoteright quoteright",
- -- quotedblleft = "grave grave",
- -- quotedblright = "quotesingle quotesingle",
- -- quotedblbase = "comma comma",
-}
-
-local tlig_specification = {
- type = "ligature",
- features = everywhere,
- data = tlig,
- order = { "tlig" },
- flags = noflags,
- prepend = true,
-}
-
-otf.addfeature("tlig",tlig_specification)
-
-registerotffeature {
- -- this makes it a known feature (in tables)
- name = 'tlig',
- description = 'tex ligatures',
-}
-
--- trep
-
-local trep = {
- -- [0x0022] = 0x201D,
- [0x0027] = 0x2019,
- -- [0x0060] = 0x2018,
-}
-
-local trep_specification = {
- type = "substitution",
- features = everywhere,
- data = trep,
- order = { "trep" },
- flags = noflags,
- prepend = true,
-}
-
-otf.addfeature("trep",trep_specification)
-
-registerotffeature {
- -- this makes it a known feature (in tables)
- name = 'trep',
- description = 'tex replacements',
-}
-
--- -- tcom (obsolete, was already not set for a while)
-
--- if characters.combined then
---
--- local tcom = { }
---
--- local function initialize()
--- characters.initialize()
--- for first, seconds in next, characters.combined do
--- for second, combination in next, seconds do
--- tcom[combination] = { first, second }
--- end
--- end
--- -- return false
--- end
---
--- local tcom_specification = {
--- type = "ligature",
--- features = everywhere,
--- data = tcom,
--- order = { "tcom" },
--- flags = noflags,
--- initialize = initialize,
--- }
---
--- otf.addfeature("tcom",tcom_specification)
---
--- registerotffeature {
--- name = 'tcom',
--- description = 'tex combinations',
--- }
---
--- end
-
--- anum
-
-local anum_arabic = {
- [0x0030] = 0x0660,
- [0x0031] = 0x0661,
- [0x0032] = 0x0662,
- [0x0033] = 0x0663,
- [0x0034] = 0x0664,
- [0x0035] = 0x0665,
- [0x0036] = 0x0666,
- [0x0037] = 0x0667,
- [0x0038] = 0x0668,
- [0x0039] = 0x0669,
-}
-
-local anum_persian = {
- [0x0030] = 0x06F0,
- [0x0031] = 0x06F1,
- [0x0032] = 0x06F2,
- [0x0033] = 0x06F3,
- [0x0034] = 0x06F4,
- [0x0035] = 0x06F5,
- [0x0036] = 0x06F6,
- [0x0037] = 0x06F7,
- [0x0038] = 0x06F8,
- [0x0039] = 0x06F9,
-}
-
-local function valid(data)
- local features = data.resources.features
- if features then
- for k, v in next, features do
- for k, v in next, v do
- if v.arab then
- return true
- end
- end
- end
- end
-end
-
-local anum_specification = {
- {
- type = "substitution",
- features = { arab = { urd = true, dflt = true } },
- order = { "anum" },
- data = anum_arabic,
- flags = noflags, -- { },
- valid = valid,
- },
- {
- type = "substitution",
- features = { arab = { urd = true } },
- order = { "anum" },
- data = anum_persian,
- flags = noflags, -- { },
- valid = valid,
- },
-}
-
-otf.addfeature("anum",anum_specification) -- todo: only when there is already an arab script feature
-
-registerotffeature {
- -- this makes it a known feature (in tables)
- name = 'anum',
- description = 'arabic digits',
-}
-
--- maybe:
-
--- fonts.handlers.otf.addfeature("hangulfix",{
--- type = "substitution",
--- features = { ["hang"] = { ["*"] = true } },
--- data = {
--- [0x1160] = 0x119E,
--- },
--- order = { "hangulfix" },
--- flags = { },
--- prepend = true,
--- })
-
-- fonts.handlers.otf.features.register {
-- name = 'hangulfix',
-- description = 'fixes for hangul',
@@ -1028,126 +873,3 @@ registerotffeature {
-- a = { b = -500 },
-- }
-- }
-
--- This is a quick and dirty hack.
-
-local lookups = { }
-local protect = { }
-local revert = { }
-local zwjchar = 0x200C
-local zwj = { zwjchar }
-
-otf.addfeature {
- name = "blockligatures",
- type = "chainsubstitution",
- nocheck = true, -- because there is no 0x200C in the font
- prepend = true, -- make sure we do it early
- future = true, -- avoid nilling due to no steps yet
- lookups = {
- {
- type = "multiple",
- data = lookups,
- },
- },
- data = {
- rules = protect,
- }
-}
-
-otf.addfeature {
- name = "blockligatures",
- type = "chainsubstitution",
- nocheck = true, -- because there is no 0x200C in the font
- append = true, -- this is done late
- overload = false, -- we don't want to overload the previous definition
- lookups = {
- {
- type = "ligature",
- data = lookups,
- },
- },
- data = {
- rules = revert,
- }
-}
-
-registerotffeature {
- name = 'blockligatures',
- description = 'block certain ligatures',
-}
-
-local settings_to_array = utilities.parsers and utilities.parsers.settings_to_array
- or function(s) return string.split(s,",") end -- for generic
-
-local splitter = lpeg.splitat(":")
-
-local function blockligatures(str)
-
- local t = settings_to_array(str)
-
- for i=1,#t do
- local ti = t[i]
- local before, current, after = lpegmatch(splitter,ti)
- if current and after then -- before is returned when no match
- -- experimental joke
- if before then
- before = utfsplit(before)
- for i=1,#before do
- before[i] = { before[i] }
- end
- end
- if current then
- current = utfsplit(current)
- end
- if after then
- after = utfsplit(after)
- for i=1,#after do
- after[i] = { after[i] }
- end
- end
- else
- before = nil
- current = utfsplit(ti)
- after = nil
- end
- if #current > 1 then
- local one = current[1]
- local two = current[2]
- lookups[one] = { one, zwjchar }
- local one = { one }
- local two = { two }
- local new = #protect + 1
- protect[new] = {
- before = before,
- current = { one, two },
- after = after,
- lookups = { 1 }, -- not shared !
- }
- revert[new] = {
- -- before = before,
- current = { one, zwj },
- -- after = { two, unpack(after) },
- after = { two },
- lookups = { 1 }, -- not shared !
- }
- end
- end
-end
-
--- blockligatures("\0\0")
-
-otf.helpers.blockligatures = blockligatures
-
--- blockligatures("fi,ff")
--- blockligatures("fl")
--- blockligatures("u:fl:age")
-
-if context then
-
- interfaces.implement {
- name = "blockligatures",
- arguments = "string",
- actions = blockligatures,
- }
-
-end
diff --git a/tex/context/base/mkiv/font-otj.lua b/tex/context/base/mkiv/font-otj.lua
index 9037939df..bb3038935 100644
--- a/tex/context/base/mkiv/font-otj.lua
+++ b/tex/context/base/mkiv/font-otj.lua
@@ -97,8 +97,11 @@ local setlink = nuts.setlink
local setwidth = nuts.setwidth
local getwidth = nuts.getwidth
-local traverse_id = nuts.traverse_id
-local traverse_char = nuts.traverse_char
+----- traverse_id = nuts.traverse_id
+----- traverse_char = nuts.traverse_char
+local nextchar = nuts.traversers.char
+local nextglue = nuts.traversers.glue
+
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
@@ -128,6 +131,10 @@ do if not fontkern then -- generic
return n
end
+end end
+
+do if not italickern then -- generic
+
local thekern = nuts.new("kern",3) -- italiccorrection
local setkern = nuts.setkern
local copy_node = nuts.copy_node
@@ -298,10 +305,10 @@ end
-- kind: 0=single 1=first of pair, 2=second of pair
function injections.setposition(kind,current,factor,rlmode,spec,injection)
- local x = factor*spec[1]
- local y = factor*spec[2]
- local w = factor*spec[3]
- local h = factor*spec[4]
+ local x = factor * (spec[1] or 0)
+ local y = factor * (spec[2] or 0)
+ local w = factor * (spec[3] or 0)
+ local h = factor * (spec[4] or 0)
if x ~= 0 or w ~= 0 or y ~= 0 or h ~= 0 then -- okay?
local yoffset = y - h
local leftkern = x -- both kerns are set in a pair kern compared
@@ -449,7 +456,8 @@ function injections.setmove(current,factor,rlmode,x,injection)
end
function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark) -- ba=baseanchor, ma=markanchor
- local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
+ local dx = factor*(ba[1]-ma[1])
+ local dy = factor*(ba[2]-ma[2])
nofregisteredmarks = nofregisteredmarks + 1
if rlmode >= 0 then
dx = tfmbase.width - dx -- see later commented ox
@@ -462,15 +470,18 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmar
if i.markmark then
-- out of order mkmk: yes or no or option
else
- if dx ~= 0 then
- i.markx = dx
- end
- if y ~= 0 then
- i.marky = dy
- end
- if rlmode then
- i.markdir = rlmode
- end
+ -- if dx ~= 0 then
+ -- i.markx = dx
+ -- end
+ -- if y ~= 0 then
+ -- i.marky = dy
+ -- end
+ -- if rlmode then
+ -- i.markdir = rlmode
+ -- end
+ i.markx = dx
+ i.marky = dy
+ i.markdir = rlmode or 0
i.markbase = nofregisteredmarks
i.markbasenode = base
i.markmark = mkmk
@@ -558,7 +569,7 @@ end
local function showsub(n,what,where)
report_injections("begin subrun: %s",where)
- for n in traverse_char(n) do
+ for n in nextchar, n do
showchar(n,where)
show(n,what,where," ")
end
@@ -628,7 +639,6 @@ end
-- +D-replace +D-replace
local function inject_kerns_only(head,where)
- head = tonut(head)
if trace_injections then
trace(head,"kerns")
end
@@ -684,7 +694,8 @@ local function inject_kerns_only(head,where)
-- glyph|disc|glyph (special case)
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
- setfield(prev,"replace",fontkern(leftkern)) -- maybe also leftkern
+ replace = fontkern(leftkern)
+ done = true
end
end
end
@@ -704,7 +715,7 @@ local function inject_kerns_only(head,where)
local done = false
if pre then
-- left|pre glyphs|right
- for n in traverse_char(pre) do
+ for n in nextchar, pre do
local p = rawget(properties,n)
if p then
local i = p.injections or p.preinjections
@@ -720,7 +731,7 @@ local function inject_kerns_only(head,where)
end
if post then
-- left|post glyphs|right
- for n in traverse_char(post) do
+ for n in nextchar, post do
local p = rawget(properties,n)
if p then
local i = p.injections or p.postinjections
@@ -736,7 +747,7 @@ local function inject_kerns_only(head,where)
end
if replace then
-- left|replace glyphs|right
- for n in traverse_char(replace) do
+ for n in nextchar, replace do
local p = rawget(properties,n)
if p then
local i = p.injections or p.replaceinjections
@@ -771,11 +782,10 @@ local function inject_kerns_only(head,where)
if trace_injections then
show_result(head)
end
- return tonode(head), true
+ return head
end
local function inject_positions_only(head,where)
- head = tonut(head)
if trace_injections then
trace(head,"positions")
end
@@ -826,7 +836,9 @@ local function inject_positions_only(head,where)
if replace then
-- error, we expect an empty one
else
- setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern
+--KE setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern
+ replace = fontkern(rightkern) -- maybe also leftkern --KE
+ done = true --KE
end
end
end
@@ -859,7 +871,8 @@ local function inject_positions_only(head,where)
-- new .. okay?
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
- setfield(prev,"replace",fontkern(leftkern)) -- maybe also leftkern
+ replace = fontkern(leftkern)
+ done = true
end
end
end
@@ -878,7 +891,7 @@ local function inject_positions_only(head,where)
local done = false
if pre then
-- left|pre glyphs|right
- for n in traverse_char(pre) do
+ for n in nextchar, pre do
local p = rawget(properties,n)
if p then
local i = p.injections or p.preinjections
@@ -903,7 +916,7 @@ local function inject_positions_only(head,where)
end
if post then
-- left|post glyphs|right
- for n in traverse_char(post) do
+ for n in nextchar, post do
local p = rawget(properties,n)
if p then
local i = p.injections or p.postinjections
@@ -928,7 +941,7 @@ local function inject_positions_only(head,where)
end
if replace then
-- left|replace glyphs|right
- for n in traverse_char(replace) do
+ for n in nextchar, replace do
local p = rawget(properties,n)
if p then
local i = p.injections or p.replaceinjections
@@ -1002,7 +1015,7 @@ local function inject_positions_only(head,where)
if trace_injections then
show_result(head)
end
- return tonode(head), true
+ return head
end
local function showoffset(n,flag)
@@ -1013,7 +1026,6 @@ local function showoffset(n,flag)
end
local function inject_everything(head,where)
- head = tonut(head)
if trace_injections then
trace(head,"everything")
end
@@ -1276,7 +1288,8 @@ local function inject_everything(head,where)
if replace then
-- error, we expect an empty one
else
- setfield(next,"replace",fontkern(rightkern)) -- maybe also leftkern
+ replace = fontkern(rightkern)
+ done = true
end
end
end
@@ -1309,7 +1322,8 @@ local function inject_everything(head,where)
if i then
local leftkern = i.leftkern
if leftkern and leftkern ~= 0 then
- setfield(prev,"replace",fontkern(leftkern)) -- maybe also leftkern
+ replace = fontkern(leftkern)
+ done = true
end
end
end
@@ -1344,7 +1358,7 @@ local function inject_everything(head,where)
local done = false
if pre then
-- left|pre glyphs|right
- for n in traverse_char(pre) do
+ for n in nextchar, pre do
local p = rawget(properties,n)
if p then
local i = p.injections or p.preinjections
@@ -1375,7 +1389,7 @@ local function inject_everything(head,where)
end
if post then
-- left|post glyphs|right
- for n in traverse_char(post) do
+ for n in nextchar, post do
local p = rawget(properties,n)
if p then
local i = p.injections or p.postinjections
@@ -1406,7 +1420,7 @@ local function inject_everything(head,where)
end
if replace then
-- left|replace glyphs|right
- for n in traverse_char(replace) do
+ for n in nextchar, replace do
local p = rawget(properties,n)
if p then
local i = p.injections or p.replaceinjections
@@ -1514,7 +1528,7 @@ local function inject_everything(head,where)
if trace_injections then
show_result(head)
end
- return tonode(head), true
+ return head
end
-- space triggers
@@ -1603,7 +1617,7 @@ end
local function injectspaces(head)
if not triggers then
- return head, false
+ return head
end
local lastfont = nil
local spacekerns = nil
@@ -1613,7 +1627,6 @@ local function injectspaces(head)
local threshold = 0
local leftkern = false
local rightkern = false
- local nuthead = tonut(head)
local function updatefont(font,trig)
leftkerns = trig.left
@@ -1623,7 +1636,7 @@ local function injectspaces(head)
factor = getthreshold(font)
end
- for n in traverse_id(glue_code,nuthead) do
+ for n in nextglue, head do
local prev, next = getspaceboth(n)
local prevchar = prev and ischar(prev)
local nextchar = next and ischar(next)
@@ -1661,12 +1674,8 @@ local function injectspaces(head)
if trace_spaces then
report_spaces("%C [%p + %p + %p] %C",prevchar,lnew,old,rnew,nextchar)
end
- local h = insert_node_before(nuthead,n,italickern(lnew))
- if h == nuthead then
- head = tonode(h)
- nuthead = h
- end
- insert_node_after(nuthead,n,italickern(rnew))
+ head = insert_node_before(head,n,italickern(lnew))
+ insert_node_after(head,n,italickern(rnew))
else
local new = old + (leftkern + rightkern) * factor
if trace_spaces then
@@ -1681,7 +1690,7 @@ local function injectspaces(head)
if trace_spaces then
report_spaces("%C [%p + %p]",prevchar,old,new)
end
- insert_node_after(nuthead,n,italickern(new)) -- tricky with traverse but ok
+ insert_node_after(head,n,italickern(new)) -- tricky with traverse but ok
else
local new = old + leftkern * factor
if trace_spaces then
@@ -1700,7 +1709,7 @@ local function injectspaces(head)
if trace_spaces then
report_spaces("%C [%p + %p]",nextchar,old,new)
end
- insert_node_after(nuthead,n,italickern(new))
+ insert_node_after(head,n,italickern(new))
else
local new = old + rightkern * factor
if trace_spaces then
@@ -1714,7 +1723,8 @@ local function injectspaces(head)
end
triggers = false
- return head, true
+
+ return head
end
--
@@ -1740,6 +1750,6 @@ function injections.handler(head,where)
end
return inject_kerns_only(head,where)
else
- return head, false
+ return head
end
end
diff --git a/tex/context/base/mkiv/font-otl.lua b/tex/context/base/mkiv/font-otl.lua
index a71e3ad98..df83dc968 100644
--- a/tex/context/base/mkiv/font-otl.lua
+++ b/tex/context/base/mkiv/font-otl.lua
@@ -52,14 +52,14 @@ local report_otf = logs.reporter("fonts","otf loading")
local fonts = fonts
local otf = fonts.handlers.otf
-otf.version = 3.103 -- beware: also sync font-mis.lua and in mtx-fonts
-otf.cache = containers.define("fonts", "otl", otf.version, true)
-otf.svgcache = containers.define("fonts", "svg", otf.version, true)
-otf.sbixcache = containers.define("fonts", "sbix", otf.version, true)
-otf.pdfcache = containers.define("fonts", "pdf", otf.version, true)
+otf.version = 3.107 -- beware: also sync font-mis.lua and in mtx-fonts
+otf.cache = containers.define("fonts", "otl", otf.version, true)
+otf.svgcache = containers.define("fonts", "svg", otf.version, true)
+otf.pngcache = containers.define("fonts", "png", otf.version, true)
+otf.pdfcache = containers.define("fonts", "pdf", otf.version, true)
otf.svgenabled = false
-otf.sbixenabled = false
+otf.pngenabled = false
local otfreaders = otf.readers
@@ -152,17 +152,17 @@ function otf.load(filename,sub,instance)
report_otf("forced reload of %a due to hard coded flag",filename)
reload = true
end
- if reload then
+ if reload then
report_otf("loading %a, hash %a",filename,hash)
--
- starttiming(otfreaders)
+ starttiming(otfreaders,true)
data = otfreaders.loadfont(filename,sub or 1,instance) -- we can pass the number instead (if it comes from a name search)
if data then
-- todo: make this a plugin
- local used = checkmemory()
- local resources = data.resources
- local svgshapes = resources.svgshapes
- local sbixshapes = resources.sbixshapes
+ local used = checkmemory()
+ local resources = data.resources
+ local svgshapes = resources.svgshapes
+ local pngshapes = resources.pngshapes
if cleanup == 0 then
checkmemory(used,threshold,tracememory)
end
@@ -186,16 +186,16 @@ function otf.load(filename,sub,instance)
checkmemory(used,threshold,tracememory)
end
end
- if sbixshapes then
- resources.sbixshapes = nil
- if otf.sbixenabled then
+ if pngshapes then
+ resources.pngshapes = nil
+ if otf.pngenabled then
local timestamp = os.date()
-- work in progress ... a bit boring to do
- containers.write(otf.sbixcache,hash, {
- sbixshapes = sbixshapes,
- timestamp = timestamp,
+ containers.write(otf.pngcache,hash, {
+ pngshapes = pngshapes,
+ timestamp = timestamp,
})
- data.properties.sbix = {
+ data.properties.png = {
hash = hash,
timestamp = timestamp,
}
@@ -242,6 +242,7 @@ function otf.load(filename,sub,instance)
checkmemory(used,threshold,tracememory)
end
else
+ stoptiming(otfreaders)
data = nil
report_otf("loading failed due to read error")
end
@@ -405,6 +406,7 @@ local function copytotfm(data,cache_id)
local fontname = metadata.fontname
local fullname = metadata.fullname or fontname
local psname = fontname or fullname
+ local subfont = metadata.subfontindex
local units = metadata.units or 1000
--
if units == 0 then -- catch bugs in fonts
@@ -499,6 +501,7 @@ local function copytotfm(data,cache_id)
properties.fullname = fullname
properties.psname = psname
properties.name = filename or fullname
+ properties.subfont = subfont
--
-- properties.name = specification.name
-- properties.sub = specification.sub
diff --git a/tex/context/base/mkiv/font-oto.lua b/tex/context/base/mkiv/font-oto.lua
index 4b986bd3b..6f6d89d43 100644
--- a/tex/context/base/mkiv/font-oto.lua
+++ b/tex/context/base/mkiv/font-oto.lua
@@ -49,7 +49,9 @@ local function gref(descriptions,n)
return f_unicode(n)
end
elseif n then
- local num, nam, j = { }, { }, 0
+ local num = { }
+ local nam = { }
+ local j = 0
for i=1,#n do
local ni = n[i]
if tonumber(ni) then -- first is likely a key
@@ -121,8 +123,8 @@ local basehash, basehashes, applied = { }, 1, { }
local function registerbasehash(tfmdata)
local properties = tfmdata.properties
- local hash = concat(applied," ")
- local base = basehash[hash]
+ local hash = concat(applied," ")
+ local base = basehash[hash]
if not base then
basehashes = basehashes + 1
base = basehashes
@@ -310,13 +312,16 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
for i=1,nofligatures do
local ligature = ligatures[i]
- local unicode, tree = ligature[1], ligature[2]
+ local unicode = ligature[1]
+ local tree = ligature[2]
make_1(present,tree,"ctx_"..unicode)
end
for i=1,nofligatures do
- local ligature = ligatures[i]
- local unicode, tree, lookupname = ligature[1], ligature[2], ligature[3]
+ local ligature = ligatures[i]
+ local unicode = ligature[1]
+ local tree = ligature[2]
+ local lookupname = ligature[3]
make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,sequence)
end
@@ -415,36 +420,42 @@ local function checkmathreplacements(tfmdata,fullname,fixitalics)
for unicode, replacement in next, changed do
local u = characters[unicode]
local r = characters[replacement]
- local n = u.next
- local v = u.vert_variants
- local h = u.horiz_variants
- if fixitalics then
- -- quite some warnings on stix ...
- local ui = u.italic
- if ui and not r.italic then
+ if u and r then
+ local n = u.next
+ local v = u.vert_variants
+ local h = u.horiz_variants
+ if fixitalics then
+ -- quite some warnings on stix ...
+ local ui = u.italic
+ if ui and not r.italic then
+ if trace_preparing then
+ report_prepare("using %i units of italic correction from %C for %U",ui,unicode,replacement)
+ end
+ r.italic = ui -- print(ui,ri)
+ end
+ end
+ if n and not r.next then
if trace_preparing then
- report_prepare("using %i units of italic correction from %C for %U",ui,unicode,replacement)
+ report_prepare("forcing %s for %C substituted by %U","incremental step",unicode,replacement)
end
- r.italic = ui -- print(ui,ri)
+ r.next = n
end
- end
- if n and not r.next then
- if trace_preparing then
- report_prepare("forcing %s for %C substituted by %U","incremental step",unicode,replacement)
+ if v and not r.vert_variants then
+ if trace_preparing then
+ report_prepare("forcing %s for %C substituted by %U","vertical variants",unicode,replacement)
+ end
+ r.vert_variants = v
end
- r.next = n
- end
- if v and not r.vert_variants then
- if trace_preparing then
- report_prepare("forcing %s for %C substituted by %U","vertical variants",unicode,replacement)
+ if h and not r.horiz_variants then
+ if trace_preparing then
+ report_prepare("forcing %s for %C substituted by %U","horizontal variants",unicode,replacement)
+ end
+ r.horiz_variants = h
end
- r.vert_variants = v
- end
- if h and not r.horiz_variants then
+ else
if trace_preparing then
- report_prepare("forcing %s for %C substituted by %U","horizontal variants",unicode,replacement)
+ report_prepare("error replacing %C by %U",unicode,replacement)
end
- r.horiz_variants = h
end
end
end
diff --git a/tex/context/base/mkiv/font-otr.lua b/tex/context/base/mkiv/font-otr.lua
index 5bac75052..c7ff6b726 100644
--- a/tex/context/base/mkiv/font-otr.lua
+++ b/tex/context/base/mkiv/font-otr.lua
@@ -25,7 +25,7 @@ if not modules then modules = { } end modules ['font-otr'] = {
-- are just a unicode string but it doesn't save that much. It will be an option
-- some day.
--- Optimizing the widths wil be done anyway as it save quite some on a cjk font
+-- Optimizing the widths will be done anyway as it save quite some on a cjk font
-- and the existing (old) code if okay.
-- todo: more messages (only if really needed)
@@ -67,6 +67,7 @@ if not modules then modules = { } end modules ['font-otr'] = {
local next, type, tonumber = next, type, tonumber
local byte, lower, char, gsub = string.byte, string.lower, string.char, string.gsub
+local fullstrip = string.fullstrip
local floor, round = math.floor, math.round
local P, R, S, C, Cs, Cc, Ct, Carg, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Carg, lpeg.Cmt
local lpegmatch = lpeg.match
@@ -121,11 +122,47 @@ local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed num
local readfword = readshort -- 16-bit signed integer that describes a quantity in FUnits
local readufword = readushort -- 16-bit unsigned integer that describes a quantity in FUnits
local readoffset = readushort
+local readcardinaltable = streamreader.readcardinaltable
+local readintegertable = streamreader.readintegertable
function streamreader.readtag(f)
return lower(stripstring(readstring(f,4)))
end
+local short = 2
+local ushort = 2
+local ulong = 4
+
+directives.register("fonts.streamreader",function()
+
+ streamreader = utilities.streams
+
+ openfile = streamreader.open
+ closefile = streamreader.close
+ setposition = streamreader.setposition
+ skipshort = streamreader.skipshort
+ readbytes = streamreader.readbytes
+ readstring = streamreader.readstring
+ readbyte = streamreader.readcardinal1
+ readushort = streamreader.readcardinal2
+ readuint = streamreader.readcardinal3
+ readulong = streamreader.readcardinal4
+ readshort = streamreader.readinteger2
+ readlong = streamreader.readinteger4
+ readfixed = streamreader.readfixed4
+ read2dot14 = streamreader.read2dot14
+ readfword = readshort
+ readufword = readushort
+ readoffset = readushort
+ readcardinaltable = streamreader.readcardinaltable
+ readintegertable = streamreader.readintegertable
+
+ function streamreader.readtag(f)
+ return lower(stripstring(readstring(f,4)))
+ end
+
+end)
+
-- date represented in number of seconds since 12:00 midnight, January 1, 1904. The value is represented as a
-- signed 64-bit integer
@@ -704,20 +741,30 @@ readers.helpers = helpers
local function gotodatatable(f,fontdata,tag,criterium)
if criterium and f then
- local datatable = fontdata.tables[tag]
- if datatable then
- local tableoffset = datatable.offset
- setposition(f,tableoffset)
- return tableoffset
+ local tables = fontdata.tables
+ if tables then
+ local datatable = tables[tag]
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ return tableoffset
+ end
+ else
+ report("no tables")
end
end
end
local function reportskippedtable(f,fontdata,tag,criterium)
if criterium and f then
- local datatable = fontdata.tables[tag]
- if datatable then
- report("loading of table %a skipped",tag)
+ local tables = fontdata.tables
+ if tables then
+ local datatable = tables[tag]
+ if datatable then
+ report("loading of table %a skipped",tag)
+ end
+ else
+ report("no tables")
end
end
end
@@ -749,6 +796,16 @@ local platformnames = {
compatiblefullname = true,
}
+local platformextras = {
+ uniqueid = true,
+ version = true,
+ copyright = true,
+ license = true,
+ licenseurl = true,
+ manufacturer = true,
+ vendorurl = true,
+}
+
function readers.name(f,fontdata,specification)
local tableoffset = gotodatatable(f,fontdata,"name",true)
if tableoffset then
@@ -819,6 +876,18 @@ function readers.name(f,fontdata,specification)
-- and extend when we run into it (todo: proper reverse hash) .. we're only
-- interested in english anyway
--
+ local function decoded(platform,encoding,content)
+ local decoder = decoders[platform]
+ if decoder then
+ decoder = decoder[encoding]
+ end
+ if decoder then
+ return decoder(content)
+ else
+ return content
+ end
+ end
+ --
local function filter(platform,e,l)
local namelist = namelists[platform]
for i=1,#namelist do
@@ -830,14 +899,7 @@ function readers.name(f,fontdata,specification)
local language = name.language
if (not e or encoding == e) and (not l or language == l) then
setposition(f,name.offset)
- local content = readstring(f,name.length)
- local decoder = decoders[platform]
- if decoder then
- decoder = decoder[encoding]
- end
- if decoder then
- content = decoder(content)
- end
+ local content = decoded(platform,encoding,readstring(f,name.length))
if nametag then
names[nametag] = {
content = content,
@@ -864,23 +926,16 @@ function readers.name(f,fontdata,specification)
fontdata.extras = extras
--
if specification.platformnames then
- local collected = { }
+ local collected = { }
+ local platformextras = specification.platformextras and platformextras
for platform, namelist in next, namelists do
local filtered = false
for i=1,#namelist do
local entry = namelist[i]
local name = entry.name
- if platformnames[name] then
+ if platformnames[name] or (platformextras and platformextras[name]) then
setposition(f,entry.offset)
- local content = readstring(f,entry.length)
- local encoding = entry.encoding
- local decoder = decoders[platform]
- if decoder then
- decoder = decoder[encoding]
- end
- if decoder then
- content = decoder(content)
- end
+ local content = decoded(platform,entry.encoding,readstring(f,entry.length))
if filtered then
filtered[name] = content
else
@@ -923,7 +978,7 @@ readers["os/2"] = function(f,fontdata)
local version = readushort(f)
local windowsmetrics = {
version = version,
- averagewidth = readshort(f),
+ averagewidth = readshort(f), -- ushort?
weightclass = readushort(f),
widthclass = readushort(f),
fstype = readushort(f),
@@ -953,7 +1008,7 @@ readers["os/2"] = function(f,fontdata)
if version >= 1 then
windowsmetrics.codepageranges = { readulong(f), readulong(f) }
end
- if version >= 3 then
+ if version >= 2 then
windowsmetrics.xheight = readshort(f)
windowsmetrics.capheight = readshort(f)
windowsmetrics.defaultchar = readushort(f)
@@ -980,24 +1035,28 @@ end
readers.head = function(f,fontdata)
local tableoffset = gotodatatable(f,fontdata,"head",true)
if tableoffset then
+ local version = readulong(f)
+ local fontversion = readulong(f)
local fontheader = {
- version = readfixed(f),
- revision = readfixed(f),
- checksum = readulong(f),
- magic = readulong(f),
- flags = readushort(f),
- units = readushort(f),
- created = readlongdatetime(f),
- modified = readlongdatetime(f),
- xmin = readshort(f),
- ymin = readshort(f),
- xmax = readshort(f),
- ymax = readshort(f),
- macstyle = readushort(f),
- smallpixels = readushort(f),
- directionhint = readshort(f),
- indextolocformat = readshort(f),
- glyphformat = readshort(f),
+ version = version,
+ fontversion = number.to16dot16(fontversion),
+ fontversionnumber = fontversion,
+ -- checksum = readulong(f),
+ checksum = readushort(f) * 0x10000 + readushort(f),
+ magic = readulong(f),
+ flags = readushort(f),
+ units = readushort(f),
+ created = readlongdatetime(f),
+ modified = readlongdatetime(f),
+ xmin = readshort(f),
+ ymin = readshort(f),
+ xmax = readshort(f),
+ ymax = readshort(f),
+ macstyle = readushort(f),
+ smallpixels = readushort(f),
+ directionhint = readshort(f),
+ indextolocformat = readshort(f),
+ glyphformat = readshort(f),
}
fontdata.fontheader = fontheader
else
@@ -1013,7 +1072,7 @@ readers.hhea = function(f,fontdata,specification)
local tableoffset = gotodatatable(f,fontdata,"hhea",specification.details)
if tableoffset then
fontdata.horizontalheader = {
- version = readfixed(f), -- two ushorts: major minor
+ version = readulong(f),
ascender = readfword(f),
descender = readfword(f),
linegap = readfword(f),
@@ -1042,7 +1101,7 @@ readers.vhea = function(f,fontdata,specification)
local tableoffset = gotodatatable(f,fontdata,"vhea",specification.details)
if tableoffset then
fontdata.verticalheader = {
- version = readfixed(f),
+ version = readulong(f),
ascender = readfword(f),
descender = readfword(f),
linegap = readfword(f),
@@ -1075,15 +1134,15 @@ end
readers.maxp = function(f,fontdata,specification)
local tableoffset = gotodatatable(f,fontdata,"maxp",specification.details)
if tableoffset then
- local version = readfixed(f)
+ local version = readulong(f)
local nofglyphs = readushort(f)
fontdata.nofglyphs = nofglyphs
- if version == 0.5 then
+ if version == 0x00005000 then
fontdata.maximumprofile = {
version = version,
nofglyphs = nofglyphs,
}
- elseif version == 1.0 then
+ elseif version == 0x00010000 then
fontdata.maximumprofile = {
version = version,
nofglyphs = nofglyphs,
@@ -1124,15 +1183,14 @@ readers.hmtx = function(f,fontdata,specification)
local leftsidebearing = 0
for i=0,nofmetrics-1 do
local glyph = glyphs[i]
- width = readshort(f)
+ width = readshort(f) -- readushort
leftsidebearing = readshort(f)
if width ~= 0 then
glyph.width = width
end
--- for now
--- if leftsidebearing ~= 0 then
--- glyph.lsb = leftsidebearing
--- end
+ -- if leftsidebearing ~= 0 then
+ -- glyph.lsb = leftsidebearing
+ -- end
end
-- The next can happen in for instance a monospace font or in a cjk font
-- with fixed widths.
@@ -1145,7 +1203,6 @@ readers.hmtx = function(f,fontdata,specification)
-- glyph.lsb = leftsidebearing
-- end
end
- -- hm, there can be a lsb here
end
end
@@ -1195,7 +1252,7 @@ end
readers.post = function(f,fontdata,specification)
local tableoffset = gotodatatable(f,fontdata,"post",true)
if tableoffset then
- local version = readfixed(f)
+ local version = readulong(f)
fontdata.postscript = {
version = version,
italicangle = round(1000*readfixed(f))/1000,
@@ -1209,12 +1266,12 @@ readers.post = function(f,fontdata,specification)
}
if not specification.glyphs then
-- enough done
- elseif version == 1.0 then
+ elseif version == 0x00010000 then
-- mac encoding (258 glyphs)
for index=0,#standardromanencoding do
glyphs[index].name = standardromanencoding[index]
end
- elseif version == 2.0 then
+ elseif version == 0x00020000 then
local glyphs = fontdata.glyphs
local nofglyphs = readushort(f)
local indices = { }
@@ -1245,10 +1302,6 @@ readers.post = function(f,fontdata,specification)
end
end
end
- elseif version == 2.5 then
- -- depricated, will be done when needed
- elseif version == 3.0 then
- -- no ps name information
end
else
fontdata.postscript = { }
@@ -1321,34 +1374,18 @@ formatreaders[4] = function(f,fontdata,offset)
--
skipshort(f,3) -- searchrange entryselector rangeshift
--
- local endchars = { }
- local startchars = { }
- local deltas = { }
- local offsets = { }
- local indices = { }
local mapping = fontdata.mapping
local glyphs = fontdata.glyphs
local duplicates = fontdata.duplicates
local nofdone = 0
- --
- for i=1,nofsegments do
- endchars[i] = readushort(f)
- end
- local reserved = readushort(f) -- 0
- for i=1,nofsegments do
- startchars[i] = readushort(f)
- end
- for i=1,nofsegments do
- deltas[i] = readshort(f)
- end
- for i=1,nofsegments do
- offsets[i] = readushort(f)
- end
+ local endchars = readcardinaltable(f,nofsegments,ushort)
+ local reserved = readushort(f) -- 0
+ local startchars = readcardinaltable(f,nofsegments,ushort)
+ local deltas = readcardinaltable(f,nofsegments,ushort)
+ local offsets = readcardinaltable(f,nofsegments,ushort)
-- format length language nofsegments searchrange entryselector rangeshift 4-tables
- local size = (length - 2 * 2 - 5 * 2 - 4 * 2 * nofsegments) / 2
- for i=1,size-1 do
- indices[i] = readushort(f)
- end
+ local size = (length - 2 * 2 - 5 * 2 - 4 * 2 * nofsegments) / 2
+ local indices = readcardinaltable(f,size-1,ushort)
--
for segment=1,nofsegments do
local startchar = startchars[segment]
@@ -1927,14 +1964,16 @@ local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo,inst
designsize = fontdata.designsize,
minsize = fontdata.minsize,
maxsize = fontdata.maxsize,
+ boundingbox = fontheader and { fontheader.xmin or 0, fontheader.ymin or 0, fontheader.xmax or 0, fontheader.ymax or 0 } or nil,
monospaced = (tonumber(postscript.monospaced or 0) > 0) or metrics.panosewidth == "monospaced",
averagewidth = metrics.averagewidth,
- xheight = metrics.xheight,
- capheight = metrics.capheight, -- not always present and probably crap
+ xheight = metrics.xheight, -- can be missing
+ capheight = metrics.capheight or fontdata.maxy, -- can be missing
ascender = metrics.typoascender,
descender = metrics.typodescender,
platformnames = platformnames or nil,
instancenames = instancenames or nil,
+ tableoffsets = fontdata.tableoffsets,
}
if metricstoo then
local keys = {
@@ -1996,7 +2035,8 @@ local function loadtables(f,specification,offset)
}
for i=1,fontdata.noftables do
local tag = lower(stripstring(readstring(f,4)))
- local checksum = readulong(f) -- not used
+ -- local checksum = readulong(f) -- not used
+ local checksum = readushort(f) * 0x10000 + readushort(f)
local offset = readulong(f)
local length = readulong(f)
if offset + length > filesize then
@@ -2008,13 +2048,14 @@ local function loadtables(f,specification,offset)
length = length,
}
end
+-- inspect(tables)
fontdata.foundtables = sortedkeys(tables)
if tables.cff or tables.cff2 then
fontdata.format = "opentype"
else
fontdata.format = "truetype"
end
- return fontdata
+ return fontdata, tables
end
local function prepareglyps(fontdata)
@@ -2043,7 +2084,7 @@ local variablefonts_supported = (context and true) or (logs and logs.application
local function readdata(f,offset,specification)
- local fontdata = loadtables(f,specification,offset)
+ local fontdata, tables = loadtables(f,specification,offset)
if specification.glyphs then
prepareglyps(fontdata)
@@ -2182,10 +2223,20 @@ local function readdata(f,offset,specification)
readtable("math",f,fontdata,specification)
fontdata.locations = nil
- fontdata.tables = nil
fontdata.cidmaps = nil
fontdata.dictionaries = nil
-- fontdata.cff = nil
+
+ if specification.tableoffsets then
+ fontdata.tableoffsets = tables
+ setmetatableindex(tables, {
+ version = fontdata.version,
+ noftables = fontdata.noftables,
+ searchrange = fontdata.searchrange,
+ entryselector = fontdata.entryselector,
+ rangeshift = fontdata.rangeshift,
+ })
+ end
return fontdata
end
@@ -2209,12 +2260,9 @@ local function loadfontdata(specification)
fontdata = readdata(f,0,specification)
elseif version == "ttcf" then
local subfont = tonumber(specification.subfont)
- local offsets = { }
local ttcversion = readulong(f)
local nofsubfonts = readulong(f)
- for i=1,nofsubfonts do
- offsets[i] = readulong(f)
- end
+ local offsets = readcardinaltable(f,nofsubfonts,ulong)
if subfont then -- a number of not
if subfont >= 1 and subfont <= nofsubfonts then
fontdata = readdata(f,offsets[subfont],specification)
@@ -2296,12 +2344,13 @@ local function loadfont(specification,n,instance)
specification.instance = specification.instance or instance
end
local function message(str)
- report("fatal error in file %a: %s\n%s",specification.filename,str,debug.traceback())
+ report("fatal error in file %a: %s\n%s",specification.filename,str,debug and debug.traceback())
end
local ok, result = xpcall(loadfontdata,message,specification)
if ok then
return result
end
+-- return loadfontdata(specification)
end
-- we need even less, but we can have a 'detail' variant
@@ -2323,13 +2372,26 @@ function readers.loadshapes(filename,n,instance,streams)
v.math = nil
-- v.name = nil
end
+ local names = fontdata.names
+ if names then
+ for k, v in next, names do
+ names[k] = fullstrip(v.content)
+ end
+ end
end
return fontdata and {
- -- version = 0.123 -- todo
- filename = filename,
- format = fontdata.format,
- glyphs = fontdata.glyphs,
- units = fontdata.fontheader.units,
+ -- version = 0.123 -- todo
+ filename = filename,
+ format = fontdata.format,
+ glyphs = fontdata.glyphs,
+ units = fontdata.fontheader.units,
+ cffinfo = fontdata.cffinfo,
+ fontheader = fontdata.fontheader,
+ horizontalheader = fontdata.horizontalheader,
+ verticalheader = fontdata.verticalheader,
+ maximumprofile = fontdata.maximumprofile,
+ names = fontdata.names,
+ postscript = fontdata.postscript,
} or {
filename = filename,
format = "unknown",
@@ -2385,7 +2447,7 @@ function readers.loadfont(filename,n,instance)
mathconstants = fontdata.mathconstants,
colorpalettes = fontdata.colorpalettes,
svgshapes = fontdata.svgshapes,
- sbixshapes = fontdata.sbixshapes,
+ pngshapes = fontdata.pngshapes,
variabledata = fontdata.variabledata,
foundtables = fontdata.foundtables,
},
@@ -2400,10 +2462,12 @@ function readers.getinfo(filename,specification) -- string, nil|number|table
local platformnames = false
local rawfamilynames = false
local instancenames = true
+ local tableoffsets = false
if type(specification) == "table" then
subfont = tonumber(specification.subfont)
platformnames = specification.platformnames
rawfamilynames = specification.rawfamilynames
+ tableoffsets = specification.tableoffsets
else
subfont = tonumber(specification)
end
@@ -2412,6 +2476,7 @@ function readers.getinfo(filename,specification) -- string, nil|number|table
details = true,
platformnames = platformnames,
instancenames = true,
+ tableoffsets = tableoffsets,
-- rawfamilynames = rawfamilynames,
}
if fontdata then
diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua
index 25083dfce..563094fc1 100644
--- a/tex/context/base/mkiv/font-ots.lua
+++ b/tex/context/base/mkiv/font-ots.lua
@@ -82,7 +82,7 @@ mechanisms. Both put some constraints on the code here.</p>
-- Todo: check if we copy attributes to disc nodes if needed.
--
-- Todo: it would be nice if we could get rid of components. In other places we can use
--- the unicode properties.
+-- the unicode properties. We can just keep a lua table.
--
-- Remark: We do some disc juggling where we need to keep in mind that the pre, post and
-- replace fields can have prev pointers to a nesting node ... I wonder if that is still
@@ -176,8 +176,6 @@ registertracker("otf.sample", "otf.steps","otf.substitutions","otf.positi
registertracker("otf.sample.silent", "otf.steps=silent","otf.substitutions","otf.positions","otf.analyzing")
local nuts = nodes.nuts
-local tonode = nuts.tonode
-local tonut = nuts.tonut
local getfield = nuts.getfield
local getnext = nuts.getnext
@@ -191,7 +189,6 @@ local getattr = nuts.getattr
local setattr = nuts.setattr
local getprop = nuts.getprop
local setprop = nuts.setprop
-local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
local setsubtype = nuts.setsubtype
local getchar = nuts.getchar
@@ -201,10 +198,10 @@ local setdisc = nuts.setdisc
local setlink = nuts.setlink
local getcomponents = nuts.getcomponents -- the original one, not yet node-aux
local setcomponents = nuts.setcomponents -- the original one, not yet node-aux
-local getdir = nuts.getdir
local getwidth = nuts.getwidth
local ischar = nuts.is_char
+local isglyph = nuts.isglyph
local usesfont = nuts.uses_font
local insert_node_after = nuts.insert_after
@@ -215,17 +212,12 @@ local find_node_tail = nuts.tail
local flush_node_list = nuts.flush_list
local flush_node = nuts.flush_node
local end_of_math = nuts.end_of_math
-local traverse_nodes = nuts.traverse
------ traverse_id = nuts.traverse_id
-local set_components = nuts.set_components
-local take_components = nuts.take_components
-local count_components = nuts.count_components
-local copy_no_components = nuts.copy_no_components
-local copy_only_glyphs = nuts.copy_only_glyphs
local setmetatable = setmetatable
local setmetatableindex = table.setmetatableindex
+local nextnode = nuts.traversers.node
+
----- zwnj = 0x200C
----- zwj = 0x200D
@@ -240,8 +232,8 @@ local math_code = nodecodes.math
local dir_code = nodecodes.dir
local localpar_code = nodecodes.localpar
-local discretionary_code = disccodes.discretionary
-local ligature_code = glyphcodes.ligature
+local discretionarydisc_code = disccodes.discretionary
+local ligatureglyph_code = glyphcodes.ligature
local a_state = attributes.private('state')
local a_noligature = attributes.private("noligature")
@@ -458,26 +450,28 @@ end
-- start is a mark and we need to keep that one
-local take_components = getcomponents -- we overload here (for now)
-local set_components = setcomponents -- we overload here (for now)
------ get_components = getcomponents -- we overload here (for now)
+local copy_no_components = nuts.copy_no_components
+local copy_only_glyphs = nuts.copy_only_glyphs
+
+local set_components = setcomponents
+local take_components = getcomponents
local function count_components(start,marks)
- if getid(start) ~= glyph_code then
- return 0
- elseif getsubtype(start) == ligature_code then
- local i = 0
- local components = getcomponents(start)
- while components do
- i = i + count_components(components,marks)
- components = getnext(components)
+ local char = isglyph(start)
+ if char then
+ if getsubtype(start) == ligatureglyph_code then
+ local i = 0
+ local components = getcomponents(start)
+ while components do
+ i = i + count_components(components,marks)
+ components = getnext(components)
+ end
+ return i
+ elseif not marks[char] then
+ return 1
end
- return i
- elseif not marks[getchar(start)] then
- return 1
- else
- return 0
end
+ return 0
end
local function markstoligature(head,start,stop,char)
@@ -494,7 +488,7 @@ local function markstoligature(head,start,stop,char)
end
resetinjection(base)
setchar(base,char)
- setsubtype(base,ligature_code)
+ setsubtype(base,ligatureglyph_code)
set_components(base,start)
setlink(prev,base,next)
return head, base
@@ -530,7 +524,7 @@ local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfou
end
resetinjection(base)
setchar(base,char)
- setsubtype(base,ligature_code)
+ setsubtype(base,ligatureglyph_code)
set_components(base,comp)
setlink(prev,base,next)
if not discfound then
@@ -612,7 +606,7 @@ local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfou
set_components(base,copied)
replace = base
if forcediscretionaries then
- setdisc(discfound,pre,post,replace,discretionary_code)
+ setdisc(discfound,pre,post,replace,discretionarydisc_code)
else
setdisc(discfound,pre,post,replace)
end
@@ -623,7 +617,7 @@ local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfou
return head, base
end
-local function multiple_glyphs(head,start,multiple,skiphash,what) -- what to do with skiphash matches here
+local function multiple_glyphs(head,start,multiple,skiphash,what,stop) -- what to do with skiphash matches here
local nofmultiples = #multiple
if nofmultiples > 0 then
resetinjection(start)
@@ -784,23 +778,17 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
-- ok, goto next lookup
end
end
- else -- is the check for disc still valid here ? and why only replace then
+ else
local discfound = false
- local lastdisc = nil
local hasmarks = marks[startchar]
while current do
local char, id = ischar(current,currentfont)
if char then
if skiphash and skiphash[char] then
current = getnext(current)
- -- if stop then stop = current end -- ?
- else -- ligature is a tree
- local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font
+ else
+ local lg = ligature[char]
if lg then
- if not discfound and lastdisc then
- discfound = lastdisc
- lastdisc = nil
- end
if marks[char] then
hasmarks = true
end
@@ -815,58 +803,89 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
-- kind of weird
break
elseif id == disc_code then
- --
- -- Kai: see chainprocs, we probably could do the same here or was there a reason
- -- why we kept the replace check here.
- --
- -- if not discfound then
- -- discfound = current
- -- end
- -- if current == stop then
- -- break -- okay? or before the disc
- -- else
- -- current = getnext(current)
- -- end
- --
- local replace = getfield(current,"replace") -- hm: pre and post
- if replace then
- -- of{f-}{}{f}e o{f-}{}{f}fe o{-}{}{ff}e (oe and ff ligature)
- -- we can end up here when we have a start run .. testruns start at a disc but
- -- so here we have the other case: char + disc
- while replace do
- local char, id = ischar(replace,currentfont)
- if char then
- local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font
- if lg then
- if marks[char] then
- hasmarks = true -- very unlikely
- end
- ligature = lg
- replace = getnext(replace)
- else
- return head, start, false, false
- end
- else
- return head, start, false, false
- end
- end
- stop = current
- end
- lastdisc = current
- current = getnext(current)
+ discfound = current
+ break
else
break
end
end
+ -- of{f-}{}{f}e o{f-}{}{f}fe o{-}{}{ff}e (oe and ff ligature)
+ -- we can end up here when we have a start run .. testruns start at a disc but
+ -- so here we have the other case: char + disc
+ if discfound then
+ -- don't assume marks in a disc and we don't run over a disc (for now)
+ local pre, post, replace = getdisc(discfound)
+ local match
+ if replace then
+ local char = ischar(replace,currentfont)
+ if char and ligature[char] then
+ match = true
+ end
+ end
+ if not match and pre then
+ local char = ischar(pre,currentfont)
+ if char and ligature[char] then
+ match = true
+ end
+ end
+ if not match and not pre or not replace then
+ local n = getnext(discfound)
+ local char = ischar(n,currentfont)
+ if char and ligature[char] then
+ match = true
+ end
+ end
+ if match then
+ -- we force a restart
+ local ishead = head == start
+ local prev = getprev(start)
+ if stop then
+ setnext(stop)
+ local tail = getprev(stop)
+ local copy = copy_node_list(start)
+ local liat = find_node_tail(copy)
+ if pre then
+ setlink(liat,pre)
+ end
+ if replace then
+ setlink(tail,replace)
+ end
+ pre = copy
+ replace = start
+ else
+ setnext(start)
+ local copy = copy_node(start)
+ if pre then
+ setlink(copy,pre)
+ end
+ if replace then
+ setlink(start,replace)
+ end
+ pre = copy
+ replace = start
+ end
+ setdisc(discfound,pre,post,replace)
+ if prev then
+ setlink(prev,discfound)
+ else
+ setprev(discfound)
+ head = discfound
+ end
+ start = discfound
+ return head, start, true, true
+ end
+ end
local lig = ligature.ligature
if lig then
if stop then
if trace_ligatures then
local stopchar = getchar(stop)
- head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks)
+ -- head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks)
+ head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks)
logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(lig))
else
- head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks)
+ -- head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,discfound,hasmarks)
+ head, start = toligature(head,start,stop,lig,dataset,sequence,skiphash,false,hasmarks)
end
else
-- weird but happens (in some arabic font)
@@ -876,12 +895,12 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip
logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(lig))
end
end
- return head, start, true, discfound
+ return head, start, true, false
else
-- weird but happens, pseudo ligatures ... just the components
end
end
- return head, start, false, discfound
+ return head, start, false, false
end
function handlers.gpos_single(head,start,dataset,sequence,kerns,rlmode,skiphash,step,injection)
@@ -920,7 +939,8 @@ function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,skiphash,st
end
local format = step.format
if format == "pair" then
- local a, b = krn[1], krn[2]
+ local a = krn[1]
+ local b = krn[2]
if a == true then
-- zero
elseif a then -- #a > 0
@@ -1270,6 +1290,14 @@ local function getmapping(dataset,sequence,currentlookup)
end
end
+function chainprocs.gsub_remove(head,start,stop,dataset,sequence,currentlookup,rlmode,skiphash,chainindex)
+ if trace_chains then
+ logprocess("%s: removing character %s",cref(dataset,sequence,chainindex),gref(getchar(start)))
+ end
+ head, start = remove_node(head,start,true)
+ return head, getprev(start), true
+end
+
function chainprocs.gsub_single(head,start,stop,dataset,sequence,currentlookup,rlmode,skiphash,chainindex)
local mapping = currentlookup.mapping
if mapping == nil then
@@ -1380,7 +1408,7 @@ function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup
if trace_multiples then
logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement))
end
- return multiple_glyphs(head,start,replacement,skiphash,dataset[1])
+ return multiple_glyphs(head,start,replacement,skiphash,dataset[1],stop)
end
end
return head, start, false
@@ -1532,7 +1560,8 @@ function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlm
end
local format = currentlookup.format
if format == "pair" then
- local a, b = krn[1], krn[2]
+ local a = krn[1]
+ local b = krn[2]
if a == true then
-- zero
elseif a then
@@ -1986,6 +2015,9 @@ local function chainrun(head,start,last,dataset,sequence,rlmode,skiphash,ck)
logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind)
end
end
+ else
+ -- we skip but we could also delete as option .. what does an empty lookup actually mean
+ -- in opentype ... anyway, we could map it onto gsub_remove if needed
end
i = i + 1
if i > size or not start then
@@ -2625,7 +2657,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s
end
end
else
- notmatchreplace[prev] = true -- new, for Kai to check
+ -- notmatchreplace[prev] = true -- not according to Kai
end
end
prev = getprev(prev)
@@ -2754,7 +2786,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s
end
end
else
- notmatchreplace[current] = true -- new, for Kai to check
+ -- notmatchreplace[current] = true -- not according to Kai
end
current = getnext(current)
elseif id == glue_code then
@@ -2802,6 +2834,9 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode,s
notmatchpre = { }
notmatchpost = { }
notmatchreplace = { }
+ -- notmatchpre = { a = 1, b = 1 } notmatchpre .a = nil notmatchpre .b = nil
+ -- notmatchpost = { a = 1, b = 1 } notmatchpost .a = nil notmatchpost .b = nil
+ -- notmatchreplace = { a = 1, b = 1 } notmatchreplace.a = nil notmatchreplace.b = nil
end
return head, start, done
end
@@ -3159,7 +3194,7 @@ local function testrun(disc,t_run,c_run,...)
local d = d_replace > d_post and d_replace or d_post
local head = getnext(disc) -- is: next
local tail = head
- for i=1,d do
+ for i=2,d do -- must start at 2 according to Kai
local nx = getnext(tail)
local id = getid(nx)
if id == disc_code then
@@ -3419,7 +3454,7 @@ local function k_run_single(sub,injection,last,font,attr,lookupcache,step,datase
a = getattr(sub,0)
end
if not a or (a == attr) then
- for n in traverse_nodes(sub) do -- only gpos
+ for n in nextnode, sub do -- only gpos
if n == last then
break
end
@@ -3584,7 +3619,7 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase
a = getattr(sub,0)
end
if not a or (a == attr) then
- for n in traverse_nodes(sub) do -- only gpos
+ for n in nextnode, sub do -- only gpos
if n == last then
break
end
@@ -3606,129 +3641,57 @@ local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,datase
end
end
--- to be checked, nowadays we probably can assume properly matched directions
--- so maybe we no longer need a stack
-
--- local function txtdirstate(start,stack,top,rlparmode)
--- local dir = getdir(start)
--- local new = 1
--- if dir == "+TRT" then
--- top = top + 1
--- stack[top] = dir
--- new = -1
--- elseif dir == "+TLT" then
--- top = top + 1
--- stack[top] = dir
--- elseif dir == "-TRT" or dir == "-TLT" then
--- if top == 1 then
--- top = 0
--- new = rlparmode
--- else
--- top = top - 1
--- if stack[top] == "+TRT" then
--- new = -1
--- end
--- end
--- else
--- new = rlparmode
--- end
--- return getnext(start), top, new
--- end
---
--- local function pardirstate(start)
--- local dir = getdir(start)
--- local new = 0
--- if dir == "TLT" then
--- new = 1
--- elseif dir == "TRT" then
--- new = -1
--- end
--- return getnext(start), new, new
--- end
+local txtdirstate, pardirstate do -- this might change (no need for nxt in pardirstate)
-local function txtdirstate(start,stack,top,rlparmode)
- local nxt = getnext(start)
- local dir = getdir(start)
- if dir == "+TRT" then
- top = top + 1
- stack[top] = dir
- return nxt, top, -1
- elseif dir == "+TLT" then
- top = top + 1
- stack[top] = dir
- return nxt, top, 1
- elseif dir == "-TRT" or dir == "-TLT" then
- if top == 1 then
- return nxt, 0, rlparmode
- else
- top = top - 1
- if stack[top] == "+TRT" then
- return nxt, top, -1
+ local getdirection = nuts.getdirection
+ local lefttoright = 0
+ local righttoleft = 1
+
+ txtdirstate = function(start,stack,top,rlparmode)
+ local dir, pop = getdirection(start)
+ if pop then
+ if top == 1 then
+ return 0, rlparmode
else
- return nxt, top, 1
+ top = top - 1
+ if stack[top] == righttoleft then
+ return top, -1
+ else
+ return top, 1
+ end
end
+ elseif dir == lefttoright then
+ top = top + 1
+ stack[top] = lefttoright
+ return top, 1
+ elseif dir == righttoleft then
+ top = top + 1
+ stack[top] = righttoleft
+ return top, -1
+ else
+ return top, rlparmode
end
- else
- return nxt, top, rlparmode
end
-end
-local function pardirstate(start)
- local nxt = getnext(start)
- local dir = getdir(start)
- if dir == "TLT" then
- return nxt, 1, 1
- elseif dir == "TRT" then
- return nxt, -1, -1
- else
- return nxt, 0, 0
+ pardirstate = function(start)
+ local dir = getdirection(start)
+ if dir == lefttoright then
+ return 1, 1
+ elseif dir == righttoleft then
+ return -1, -1
+ -- for old times sake we we handle strings too
+ elseif dir == "TLT" then
+ return 1, 1
+ elseif dir == "TRT" then
+ return -1, -1
+ else
+ return 0, 0
+ end
end
+
end
--- -- this will become:
---
--- local getdirection = nuts.getdirection
---
--- local function txtdirstate1(start,stack,top,rlparmode)
--- local nxt = getnext(start)
--- local dir, sub = getdirection(start)
--- if sub then
--- if top == 1 then
--- return nxt, 0, rlparmode
--- elseif dir < 2 then
--- top = top - 1
--- if stack[top] == 1 then
--- return nxt, top, -1
--- else
--- return nxt, top, 1
--- end
--- else
--- return nxt, top, rlparmode
--- end
--- elseif dir == 1 then
--- top = top + 1
--- stack[top] = 1
--- return nxt, top, -1
--- elseif dir == 0 then
--- top = top + 1
--- stack[top] = 0
--- return nxt, top, 1
--- else
--- return nxt, top, rlparmode
--- end
--- end
---
--- local function pardirstate1(start)
--- local nxt = getnext(start)
--- local dir = getdirection(start)
--- if dir == 0 then
--- return nxt, 1, 1
--- elseif dir == 1 then
--- return nxt, -1, -1
--- else
--- return nxt, 0, 0
--- end
--- end
+-- These are non public helpers that can change without notice!
otf.helpers = otf.helpers or { }
otf.helpers.txtdirstate = txtdirstate
@@ -3832,20 +3795,23 @@ do
-- attr = false
-- end
- local head = tonut(head)
-
if trace_steps then
checkstep(head)
end
- local initialrl = direction == "TRT" and -1 or 0
- -- local initialrl = (direction == 1 or direction == "TRT") and -1 or 0
+ local initialrl = 0
- local done = false
- -- local datasets = otf.dataset(tfmdata,font,attr)
+ if getid(head) == localpar_code and getsubtype(head) == 0 then
+ initialrl = pardirstate(head)
+ elseif direction == 1 or direction == "TRT" then
+ initialrl = -1
+ end
+
+ -- local done = false
local datasets = otfdataset(tfmdata,font,attr)
- local dirstack = { } -- could move outside function but we can have local runs
+ local dirstack = { nil } -- could move outside function but we can have local runs
sweephead = { }
+ -- sweephead = { a = 1, b = 1 } sweephead.a = nil sweephead.b = nil
-- Keeping track of the headnode is needed for devanagari. (I generalized it a bit
-- so that multiple cases are also covered.) We could prepend a temp node.
@@ -3872,9 +3838,9 @@ do
-- are not frozen as we might extend or change this. Is this used at all apart from some
-- experiments?
local h, ok = handler(head,dataset,sequence,initialrl,font,attr) -- less arguments now
- if ok then
- done = true
- end
+ -- if ok then
+ -- done = true
+ -- end
if h and h ~= head then
head = h
end
@@ -3907,7 +3873,7 @@ do
local ok
head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step)
if ok then
- done = true
+ -- done = true
break
end
end
@@ -3948,12 +3914,14 @@ do
a = true
end
if a then
- local ok
- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step)
- if ok then
- done = true
- end
- if start then
+ local ok, df
+ head, start, ok, df = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step)
+ -- if ok then
+ -- done = true
+ -- end
+ if df then
+-- print("restart 1",typ)
+ elseif start then
start = getnext(start)
end
else
@@ -3976,18 +3944,20 @@ do
else
start, ok = comprun(start,c_run_single, font,attr,lookupcache,step,dataset,sequence,rlmode,skiphash,handler)
end
- if ok then
- done = true
- end
+ -- if ok then
+ -- done = true
+ -- end
else
start = getnext(start)
end
elseif id == math_code then
start = getnext(end_of_math(start))
elseif id == dir_code then
- start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
- elseif id == localpar_code then
- start, rlparmode, rlmode = pardirstate(start)
+ topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
+ start = getnext(start)
+ -- elseif id == localpar_code then
+ -- rlparmode, rlmode = pardirstate(start)
+ -- start = getnext(start)
else
start = getnext(start)
end
@@ -4011,6 +3981,7 @@ do
a = true
end
if a then
+ local ok, df
for i=m[1],m[2] do
local step = steps[i]
-- for i=1,#m do
@@ -4019,10 +3990,12 @@ do
local lookupmatch = lookupcache[char]
if lookupmatch then
-- we could move all code inline but that makes things even more unreadable
- local ok
- head, start, ok = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step)
- if ok then
- done = true
+-- local ok, df
+ head, start, ok, df = handler(head,start,dataset,sequence,lookupmatch,rlmode,skiphash,step)
+ if df then
+ break
+ elseif ok then
+ -- done = true
break
elseif not start then
-- don't ask why ... shouldn't happen
@@ -4030,7 +4003,9 @@ do
end
end
end
- if start then
+ if df then
+-- print("restart 2",typ)
+ elseif start then
start = getnext(start)
end
else
@@ -4053,18 +4028,20 @@ do
else
start, ok = comprun(start,c_run_multiple, font,attr,steps,nofsteps,dataset,sequence,rlmode,skiphash,handler)
end
- if ok then
- done = true
- end
+ -- if ok then
+ -- done = true
+ -- end
else
start = getnext(start)
end
elseif id == math_code then
start = getnext(end_of_math(start))
elseif id == dir_code then
- start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
- elseif id == localpar_code then
- start, rlparmode, rlmode = pardirstate(start)
+ topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
+ start = getnext(start)
+ -- elseif id == localpar_code then
+ -- rlparmode, rlmode = pardirstate(start)
+ -- start = getnext(start)
else
start = getnext(start)
end
@@ -4079,12 +4056,12 @@ do
end
nesting = nesting - 1
- head = tonode(head)
- return head, done
+ -- return head, done
+ return head
end
- -- This is not an official helpoer and used for tracing experiments. It can be changed as I like
+ -- This is not an official helper and used for tracing experiments. It can be changed as I like
-- at any moment. At some point it might be used in a module that can help font development.
function otf.datasetpositionprocessor(head,font,direction,dataset)
@@ -4118,12 +4095,10 @@ do
local steps = sequence.steps
local nofsteps = sequence.nofsteps
- local head = tonut(head)
local done = false
- local dirstack = { } -- could move outside function but we can have local runs
+ local dirstack = { nil } -- could move outside function but we can have local runs (maybe a few more nils)
local start = head
- local initialrl = direction == "TRT" and -1 or 0
- -- local initialrl = (direction == 1 or direction == "TRT") and -1 or 0
+ local initialrl = (direction == 1 or direction == "TRT") and -1 or 0
local rlmode = initialrl
local rlparmode = initialrl
local topstack = 0
@@ -4173,15 +4148,17 @@ do
elseif id == math_code then
start = getnext(end_of_math(start))
elseif id == dir_code then
- start, topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
- elseif id == localpar_code then
- start, rlparmode, rlmode = pardirstate(start)
+ topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode)
+ start = getnext(start)
+ -- elseif id == localpar_code then
+ -- rlparmode, rlmode = pardirstate(start)
+ -- start = getnext(start)
else
start = getnext(start)
end
end
- return tonode(head) -- , matches
+ return head
end
-- end of experiment
@@ -4193,9 +4170,26 @@ end
local plugins = { }
otf.plugins = plugins
+local report = logs.reporter("fonts")
+
function otf.registerplugin(name,f)
if type(name) == "string" and type(f) == "function" then
plugins[name] = { name, f }
+ report()
+ report("plugin %a has been loaded, please be aware of possible side effects",name)
+ report()
+ if logs.pushtarget then
+ logs.pushtarget("log")
+ end
+ report("Plugins are not officially supported unless stated otherwise. This is because")
+ report("they bypass the regular font handling and therefore some features in ConTeXt")
+ report("(especially those related to fonts) might not work as expected or might not work")
+ report("at all. Some plugins are for testing and development only and might change")
+ report("whenever we feel the need for it.")
+ report()
+ if logs.poptarget then
+ logs.poptarget()
+ end
end
end
diff --git a/tex/context/base/mkiv/font-ott.lua b/tex/context/base/mkiv/font-ott.lua
index 59d92f40d..10420f6ee 100644
--- a/tex/context/base/mkiv/font-ott.lua
+++ b/tex/context/base/mkiv/font-ott.lua
@@ -8,7 +8,8 @@ if not modules then modules = { } end modules ["font-ott"] = {
}
local type, next, tonumber, tostring, rawget, rawset = type, next, tonumber, tostring, rawget, rawset
-local gsub, lower, format, match = string.gsub, string.lower, string.format, string.match
+local gsub, lower, format, match, gmatch, find = string.gsub, string.lower, string.format, string.match, string.gmatch, string.find
+local sequenced = table.sequenced
local is_boolean = string.is_boolean
local setmetatableindex = table.setmetatableindex
@@ -389,6 +390,7 @@ local languages = allocate {
["kiu" ] = "kirmanjki",
["kjd" ] = "southern kiwai",
["kjp" ] = "eastern pwo karen",
+ ["kjz" ] = "bumthangkha",
["kkn" ] = "kokni",
["klm" ] = "kalmyk",
["kmb" ] = "kamba",
@@ -477,6 +479,7 @@ local languages = allocate {
["mdr" ] = "mandar",
["men" ] = "me'en",
["mer" ] = "meru",
+ ["mfa" ] = "pattani malay",
["mfe" ] = "morisyen",
["min" ] = "minangkabau",
["miz" ] = "mizo",
@@ -674,6 +677,7 @@ local languages = allocate {
["tpi" ] = "tok pisin",
["trk" ] = "turkish",
["tsg" ] = "tsonga",
+ ["tsj" ] = "tshangla",
["tua" ] = "turoyo aramaic",
["tul" ] = "tulu",
["tuv" ] = "tuvin",
@@ -704,6 +708,7 @@ local languages = allocate {
["xbd" ] = "lü",
["xhs" ] = "xhosa",
["xjb" ] = "minjangbal",
+ ["xkf" ] = "khengkha",
["xog" ] = "soga",
["xpe" ] = "kpelle (liberia)",
["yak" ] = "sakha",
@@ -987,9 +992,13 @@ setmetatableindex(languages, function(t,k)
return "dflt"
end)
-setmetatablenewindex(languages, "ignore")
-setmetatablenewindex(baselines, "ignore")
-setmetatablenewindex(baselines, "ignore")
+if setmetatablenewindex then
+
+ setmetatablenewindex(languages, "ignore")
+ setmetatablenewindex(scripts, "ignore")
+ setmetatablenewindex(baselines, "ignore")
+
+end
local function resolve(t,k)
if k then
@@ -1029,7 +1038,11 @@ local function assign(t,k,v)
end
end
-setmetatablenewindex(features, assign)
+if setmetatablenewindex then
+
+ setmetatablenewindex(features, assign)
+
+end
local checkers = {
rand = function(v)
@@ -1085,7 +1098,7 @@ storage.register("fonts/otf/usedfeatures", usedfeatures, "fonts.handlers.otf.sta
local normalizedaxis = otf.readers.helpers.normalizedaxis or function(s) return s end
-function otffeatures.normalize(features)
+function otffeatures.normalize(features,wrap) -- wrap is for context
if features then
local h = { }
for key, value in next, features do
@@ -1098,9 +1111,9 @@ function otffeatures.normalize(features)
h.script = rawget(verbosescripts,v) or (scripts[v] and v) or "dflt" -- auto adds
elseif k == "axis" then
h[k] = normalizedaxis(value)
-if not callbacks.supported.glyph_stream_provider then
- h.variableshapes = true -- for the moment
-end
+ if not callbacks.supported.glyph_stream_provider then
+ h.variableshapes = true -- for the moment
+ end
else
local uk = usedfeatures[key]
local uv = uk[value]
@@ -1113,10 +1126,27 @@ end
elseif type(value) == "string" then
local b = is_boolean(value)
if type(b) == "nil" then
- uv = lower(value)
+ -- we do this elsewhere
+ --
+ -- if find(value,"=") then
+ -- local t = { }
+ -- for k, v in gmatch(value,"([^%s,=]+)%s*=%s*([^%s,=]+)") do
+ -- t[k] = tonumber(v) or v
+ -- end
+ -- if next(t) then
+ -- value = sequenced(t,",")
+ -- end
+ -- end
+ if wrap and find(value,",") then
+ uv = "{"..lower(value).."}"
+ else
+ uv = lower(value)
+ end
else
uv = b
end
+ elseif type(value) == "table" then
+ uv = sequenced(t,",")
else
uv = value
end
diff --git a/tex/context/base/mkiv/font-oup.lua b/tex/context/base/mkiv/font-oup.lua
index 79ac76abe..d1faadbf7 100644
--- a/tex/context/base/mkiv/font-oup.lua
+++ b/tex/context/base/mkiv/font-oup.lua
@@ -11,27 +11,34 @@ local P, R, S = lpeg.P, lpeg.R, lpeg.S
local lpegmatch = lpeg.match
local insert, remove, copy, unpack = table.insert, table.remove, table.copy, table.unpack
-local formatters = string.formatters
-local sortedkeys = table.sortedkeys
-local sortedhash = table.sortedhash
-local tohash = table.tohash
-local setmetatableindex = table.setmetatableindex
-
-local report = logs.reporter("otf reader")
-
-local trace_markwidth = false trackers.register("otf.markwidth",function(v) trace_markwidth = v end)
-
-local readers = fonts.handlers.otf.readers
-local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
-
-local f_private = formatters["P%05X"]
-local f_unicode = formatters["U%05X"]
-local f_index = formatters["I%05X"]
-local f_character_y = formatters["%C"]
-local f_character_n = formatters["[ %C ]"]
-
-local check_duplicates = true -- can become an option (pseudo feature) / aways needed anyway
-local check_soft_hyphen = true -- can become an option (pseudo feature) / needed for tagging
+local formatters = string.formatters
+local sortedkeys = table.sortedkeys
+local sortedhash = table.sortedhash
+local tohash = table.tohash
+local setmetatableindex = table.setmetatableindex
+
+local report_error = logs.reporter("otf reader","error")
+local report_markwidth = logs.reporter("otf reader","markwidth")
+local report_cleanup = logs.reporter("otf reader","cleanup")
+local report_optimizations = logs.reporter("otf reader","merges")
+local report_unicodes = logs.reporter("otf reader","unicodes")
+
+local trace_markwidth = false trackers.register("otf.markwidth", function(v) trace_markwidth = v end)
+local trace_cleanup = false trackers.register("otf.cleanups", function(v) trace_cleanups = v end)
+local trace_optimizations = false trackers.register("otf.optimizations", function(v) trace_optimizations = v end)
+local trace_unicodes = false trackers.register("otf.unicodes", function(v) trace_unicodes = v end)
+
+local readers = fonts.handlers.otf.readers
+local privateoffset = fonts.constructors and fonts.constructors.privateoffset or 0xF0000 -- 0x10FFFF
+
+local f_private = formatters["P%05X"]
+local f_unicode = formatters["U%05X"]
+local f_index = formatters["I%05X"]
+local f_character_y = formatters["%C"]
+local f_character_n = formatters["[ %C ]"]
+
+local check_duplicates = true -- can become an option (pseudo feature) / aways needed anyway
+local check_soft_hyphen = true -- can become an option (pseudo feature) / needed for tagging
directives.register("otf.checksofthyphen",function(v)
check_soft_hyphen = v
@@ -67,6 +74,8 @@ local function unifyresources(fontdata,indices)
return
end
--
+ local nofindices = #indices
+ --
local variants = fontdata.resources.variants
if variants then
for selector, unicodes in next, variants do
@@ -83,8 +92,8 @@ local function unifyresources(fontdata,indices)
local u = indices[k]
if u then
newmarks[u] = v
- else
- report("discarding mark %i",k)
+ elseif trace_optimizations then
+ report_optimizations("discarding mark %i",k)
end
end
return newmarks
@@ -123,7 +132,12 @@ local function unifyresources(fontdata,indices)
if not done[c] then
local t = { }
for k, v in next, c do
- t[indices[k]] = v
+ local ug = indices[k]
+ if ug then
+ t[ug] = v
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",1,"coverage",k,nofindices)
+ end
end
cover[i] = t
done[c] = d
@@ -131,11 +145,16 @@ local function unifyresources(fontdata,indices)
end
end
--
- local function recursed(c) -- ligs are not packed
+ local function recursed(c,kind) -- ligs are not packed
local t = { }
for g, d in next, c do
if type(d) == "table" then
- t[indices[g]] = recursed(d)
+ local ug = indices[g]
+ if ug then
+ t[ug] = recursed(d,kind)
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",1,kind,g,nofindices)
+ end
else
t[g] = indices[d] -- ligature
end
@@ -167,19 +186,31 @@ local function unifyresources(fontdata,indices)
if duplicates then
for g1, d1 in next, c do
local ug1 = indices[g1]
- local ud1 = indices[d1]
- t1[ug1] = ud1
- --
- local dg1 = duplicates[ug1]
- if dg1 then
- for u in next, dg1 do
- t1[u] = ud1
+ if ug1 then
+ local ud1 = indices[d1]
+ if ud1 then
+ t1[ug1] = ud1
+ local dg1 = duplicates[ug1]
+ if dg1 then
+ for u in next, dg1 do
+ t1[u] = ud1
+ end
+ end
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",3,kind,d1,nofindices)
end
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",1,kind,g1,nofindices)
end
end
else
for g1, d1 in next, c do
- t1[indices[g1]] = indices[d1]
+ local ug1 = indices[g1]
+ if ug1 then
+ t1[ug1] = indices[d1]
+ else
+ report_error("fuzzy case %i in unifying %s: %i",2,kind,g1)
+ end
end
end
done[c] = t1
@@ -193,15 +224,25 @@ local function unifyresources(fontdata,indices)
if not t1 then
t1 = { }
for g1, d1 in next, c do
- local t2 = done[d1]
- if not t2 then
- t2 = { }
- for g2, d2 in next, d1 do
- t2[indices[g2]] = d2
+ local ug1 = indices[g1]
+ if ug1 then
+ local t2 = done[d1]
+ if not t2 then
+ t2 = { }
+ for g2, d2 in next, d1 do
+ local ug2 = indices[g2]
+ if ug2 then
+ t2[ug2] = d2
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",1,kind,g2,nofindices,nofindices)
+ end
+ end
+ done[d1] = t2
end
- done[d1] = t2
+ t1[ug1] = t2
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",2,kind,g1,nofindices)
end
- t1[indices[g1]] = t2
end
done[c] = t1
end
@@ -210,7 +251,7 @@ local function unifyresources(fontdata,indices)
elseif kind == "gsub_ligature" then
local c = step.coverage
if c then
- step.coverage = recursed(c)
+ step.coverage = recursed(c,kind)
end
elseif kind == "gsub_alternate" or kind == "gsub_multiple" then
local c = step.coverage
@@ -221,22 +262,37 @@ local function unifyresources(fontdata,indices)
if duplicates then
for g1, d1 in next, c do
for i=1,#d1 do
- d1[i] = indices[d1[i]]
+ local d1i = d1[i]
+ local d1u = indices[d1i]
+ if d1u then
+ d1[i] = d1u
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",1,kind,i,d1i,nofindices)
+ end
end
local ug1 = indices[g1]
- t1[ug1] = d1
- --
- local dg1 = duplicates[ug1]
- if dg1 then
- for u in next, dg1 do
- t1[u] = copy(d1)
+ if ug1 then
+ t1[ug1] = d1
+ local dg1 = duplicates[ug1]
+ if dg1 then
+ for u in next, dg1 do
+ t1[u] = copy(d1)
+ end
end
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",2,kind,g1,nofindices)
end
end
else
for g1, d1 in next, c do
for i=1,#d1 do
- d1[i] = indices[d1[i]]
+ local d1i = d1[i]
+ local d1u = indices[d1i]
+ if d1u then
+ d1[i] = d1u
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",2,kind,d1i,nofindices)
+ end
end
t1[indices[g1]] = d1
end
@@ -245,6 +301,41 @@ local function unifyresources(fontdata,indices)
end
step.coverage = t1
end
+ elseif kind == "gpos_single" then
+ local c = step.coverage
+ if c then
+ local t1 = done[c]
+ if not t1 then
+ t1 = { }
+ if duplicates then
+ for g1, d1 in next, c do
+ local ug1 = indices[g1]
+ if ug1 then
+ t1[ug1] = d1
+ local dg1 = duplicates[ug1]
+ if dg1 then
+ for u in next, dg1 do
+ t1[u] = d1
+ end
+ end
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",1,kind,g1,nofindices)
+ end
+ end
+ else
+ for g1, d1 in next, c do
+ local ug1 = indices[g1]
+ if ug1 then
+ t1[ug1] = d1
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",2,kind,g1,nofindices)
+ end
+ end
+ end
+ done[c] = t1
+ end
+ step.coverage = t1
+ end
elseif kind == "gpos_mark2base" or kind == "gpos_mark2mark" or kind == "gpos_mark2ligature" then
local c = step.coverage
if c then
@@ -252,7 +343,12 @@ local function unifyresources(fontdata,indices)
if not t1 then
t1 = { }
for g1, d1 in next, c do
- t1[indices[g1]] = d1
+ local ug1 = indices[g1]
+ if ug1 then
+ t1[ug1] = d1
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",1,kind,g1,nofindices)
+ end
end
done[c] = t1
end
@@ -267,7 +363,12 @@ local function unifyresources(fontdata,indices)
if not t2 then
t2 = { }
for g2, d2 in next, d1 do
- t2[indices[g2]] = d2
+ local ug2 = indices[g2]
+ if ug2 then
+ t2[ug2] = d2
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",2,kind,g2,nofindices)
+ end
end
done[d1] = t2
end
@@ -276,7 +377,7 @@ local function unifyresources(fontdata,indices)
done[c] = c
end
end
- elseif kind == "gpos_single" then
+ elseif kind == "gpos_cursive" then
local c = step.coverage
if c then
local t1 = done[c]
@@ -285,47 +386,29 @@ local function unifyresources(fontdata,indices)
if duplicates then
for g1, d1 in next, c do
local ug1 = indices[g1]
- t1[ug1] = d1
- --
- local dg1 = duplicates[ug1]
- if dg1 then
- for u in next, dg1 do
- t1[u] = d1
+ if ug1 then
+ t1[ug1] = d1
+ --
+ local dg1 = duplicates[ug1]
+ if dg1 then
+ -- probably needs a bit more
+ for u in next, dg1 do
+ t1[u] = copy(d1)
+ end
end
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",1,kind,g1,nofindices)
end
end
else
for g1, d1 in next, c do
- t1[indices[g1]] = d1
- end
- end
- done[c] = t1
- end
- step.coverage = t1
- end
- elseif kind == "gpos_cursive" then
- local c = step.coverage
- if c then
- local t1 = done[c]
- if not t1 then
- t1 = { }
- if duplicates then
- for g1, d1 in next, c do
local ug1 = indices[g1]
- t1[ug1] = d1
- --
- local dg1 = duplicates[ug1]
- if dg1 then
- -- probably needs a bit more
- for u in next, dg1 do
- t1[u] = copy(d1)
- end
+ if ug1 then
+ t1[ug1] = d1
+ else
+ report_error("case %i, bad index in unifying %s: %s of %s",2,kind,g1,nofindices)
end
end
- else
- for g1, d1 in next, c do
- t1[indices[g1]] = d1
- end
end
done[c] = t1
end
@@ -376,9 +459,13 @@ local function copyduplicates(fontdata)
if not ds or ds.width == 0 then
if ds then
descriptions[0xAD] = nil
- report("patching soft hyphen")
+ if trace_unicodes then
+ report_unicodes("patching soft hyphen")
+ end
else
- report("adding soft hyphen")
+ if trace_unicodes then
+ report_unicodes("adding soft hyphen")
+ end
end
if not duplicates then
duplicates = { }
@@ -414,10 +501,12 @@ local function copyduplicates(fontdata)
end
n = n + 1
end
- if n <= m then
- report("duplicates: %i : % t",n,t)
- else
- report("duplicates: %i : % t ...",n,t)
+ if trace_unicodes then
+ if n <= m then
+ report_unicodes("%i : % t",n,t)
+ else
+ report_unicodes("%i : % t ...",n,t)
+ end
end
else
-- what a mess
@@ -457,7 +546,6 @@ local function checklookups(fontdata,missing,nofmissing)
end
end
end
-
local function collectthem(sequences)
if not sequences then
return
@@ -549,7 +637,9 @@ local function checklookups(fontdata,missing,nofmissing)
end
end
if nofmissing <= 0 then
- report("all done in %s loops",loops)
+ if trace_unicodes then
+ report_unicodes("all missings done in %s loops",loops)
+ end
return
elseif old == nofmissing then
break
@@ -601,7 +691,9 @@ local function checklookups(fontdata,missing,nofmissing)
recursed(ligatures[i])
end
if nofmissing <= 0 then
- report("all done in %s loops",loops)
+ if trace_unicodes then
+ report_unicodes("all missings done in %s loops",loops)
+ end
return
elseif old == nofmissing then
break
@@ -611,7 +703,7 @@ local function checklookups(fontdata,missing,nofmissing)
n = 0
end
- if nofmissing > 0 then
+ if trace_unicodes and nofmissing > 0 then
local done = { }
for i, r in next, missing do
if r then
@@ -623,7 +715,7 @@ local function checklookups(fontdata,missing,nofmissing)
end
end
if next(done) then
- report("not unicoded: % t",sortedkeys(done))
+ report_unicodes("not unicoded: % t",sortedkeys(done))
end
end
end
@@ -648,6 +740,10 @@ local function unifymissing(fontdata)
resources.unicodes = nil
end
+local firstprivate = fonts.privateoffsets and fonts.privateoffsets.textbase or 0xF0000
+local puafirst = 0xE000
+local pualast = 0xF8FF
+
local function unifyglyphs(fontdata,usenames)
local private = fontdata.private or privateoffset
local glyphs = fontdata.glyphs
@@ -671,44 +767,107 @@ local function unifyglyphs(fontdata,usenames)
indices[0] = zerocode
end
--
- for index=1,#glyphs do
- local glyph = glyphs[index]
- local unicode = glyph.unicode -- this is the primary one
- if not unicode then
- -- report("assigning private unicode %U to glyph indexed %05X (%s)",private,index,"unset")
- unicode = private
- -- glyph.unicode = -1
- if names then
+ if names then
+ -- seldom uses, we don't issue message ... this branch might even go away
+ for index=1,#glyphs do
+ local glyph = glyphs[index]
+ local unicode = glyph.unicode -- this is the primary one
+ if not unicode then
+ unicode = private
local name = glyph.name or f_private(unicode)
indices[index] = name
names[name] = unicode
- else
- indices[index] = unicode
- end
- private = private + 1
- elseif descriptions[unicode] then
- -- real weird
- report("assigning private unicode %U to glyph indexed %05X (%C)",private,index,unicode)
- unicode = private
- -- glyph.unicode = -1
- if names then
+ private = private + 1
+ elseif unicode >= firstprivate then
+ unicode = private
local name = glyph.name or f_private(unicode)
indices[index] = name
names[name] = unicode
+ private = private + 1
+ elseif unicode >= puafirst and unicode <= pualast then
+ local name = glyph.name or f_private(unicode)
+ indices[index] = name
+ names[name] = unicode
+ elseif descriptions[unicode] then
+ unicode = private
+ local name = glyph.name or f_private(unicode)
+ indices[index] = name
+ names[name] = unicode
+ private = private + 1
else
- indices[index] = unicode
- end
- private = private + 1
- else
- if names then
local name = glyph.name or f_unicode(unicode)
indices[index] = name
names[name] = unicode
+ end
+ descriptions[unicode] = glyph
+ end
+ elseif trace_unicodes then
+ for index=1,#glyphs do
+ local glyph = glyphs[index]
+ local unicode = glyph.unicode -- this is the primary one
+ if not unicode then
+ unicode = private
+ indices[index] = unicode
+ private = private + 1
+ elseif unicode >= firstprivate then
+ local name = glyph.name
+ if name then
+ report_unicodes("moving glyph %a indexed %05X from private %U to %U ",name,index,unicode,private)
+ else
+ report_unicodes("moving glyph indexed %05X from private %U to %U ",index,unicode,private)
+ end
+ unicode = private
+ indices[index] = unicode
+ private = private + 1
+ elseif unicode >= puafirst and unicode <= pualast then
+ local name = glyph.name
+ if name then
+ report_unicodes("keeping private unicode %U for glyph %a indexed %05X",unicode,name,index)
+ else
+ report_unicodes("keeping private unicode %U for glyph indexed %05X",unicode,index)
+ end
+ indices[index] = unicode
+ elseif descriptions[unicode] then
+ local name = glyph.name
+ if name then
+ report_unicodes("assigning duplicate unicode %U to %U for glyph %a indexed %05X ",unicode,private,name,index)
+ else
+ report_unicodes("assigning duplicate unicode %U to %U for glyph indexed %05X ",unicode,private,index)
+ end
+ unicode = private
+ indices[index] = unicode
+ private = private + 1
else
indices[index] = unicode
end
+ descriptions[unicode] = glyph
+ end
+ else
+ for index=1,#glyphs do
+ local glyph = glyphs[index]
+ local unicode = glyph.unicode -- this is the primary one
+ if not unicode then
+ unicode = private
+ indices[index] = unicode
+ private = private + 1
+ elseif unicode >= firstprivate then
+ local name = glyph.name
+ unicode = private
+ indices[index] = unicode
+ private = private + 1
+ elseif unicode >= puafirst and unicode <= pualast then
+ local name = glyph.name
+ indices[index] = unicode
+ elseif descriptions[unicode] then
+ local name = glyph.name
+ unicode = private
+ indices[index] = unicode
+ private = private + 1
+ else
+ indices[index] = unicode
+ end
+ descriptions[unicode] = glyph
end
- descriptions[unicode] = glyph
end
--
for index=1,#glyphs do
@@ -757,37 +916,93 @@ local function unifyglyphs(fontdata,usenames)
return indices, names
end
-local p_bogusname = (
- (P("uni") + P("UNI") + P("Uni") + P("U") + P("u")) * S("Xx")^0 * R("09","AF")^1
- + (P("identity") + P("Identity") + P("IDENTITY")) * R("09","AF")^1
- + (P("index") + P("Index") + P("INDEX")) * R("09")^1
-) * P(-1)
+local p_crappyname do
+
+ local p_hex = R("af","AF","09")
+ local p_digit = R("09")
+ local p_done = S("._-")^0 + P(-1)
+ local p_alpha = R("az","AZ")
+ local p_ALPHA = R("AZ")
+
+ p_crappyname = (
+ -- (P("uni") + P("UNI") + P("Uni") + P("U") + P("u"))
+ lpeg.utfchartabletopattern({ "uni", "u" },true)
+ * S("Xx_")^0
+ * p_hex^1
+ -- + (P("identity") + P("Identity") + P("IDENTITY") + P("glyph") + P("jamo"))
+ + lpeg.utfchartabletopattern({ "identity", "glyph", "jamo" },true)
+ * p_hex^1
+ -- + (P("index") + P("Index") + P("INDEX")+ P("afii"))
+ + lpeg.utfchartabletopattern({ "index", "afii" }, true)
+ * p_digit^1
+ -- also happens l
+ + p_digit
+ * p_hex^3
+ + p_alpha
+ * p_digit^1
+ -- sort of special
+ + P("aj")
+ * p_digit^1
+ + P("eh_")
+ * (p_digit^1 + p_ALPHA * p_digit^1)
+ + (1-P("_"))^1
+ * P("_uni")
+ * p_hex^1
+ + P("_")
+ * P(1)^1
+ ) * p_done
+
+end
+
+-- In context we only keep glyph names because of tracing and access by name
+-- so weird names make no sense.
+
+local forcekeep = false -- only for testing something
+
+directives.register("otf.keepnames",function(v)
+ report_cleanup("keeping weird glyph names, expect larger files and more memory usage")
+ forcekeep = v
+end)
local function stripredundant(fontdata)
local descriptions = fontdata.descriptions
if descriptions then
local n = 0
local c = 0
- for unicode, d in next, descriptions do
- local name = d.name
- if name and lpegmatch(p_bogusname,name) then
- d.name = nil
- n = n + 1
+ -- in context we always strip
+ if (not context and fonts.privateoffsets.keepnames) or forcekeep then
+ for unicode, d in next, descriptions do
+ if d.class == "base" then
+ d.class = nil
+ c = c + 1
+ end
end
- if d.class == "base" then
- d.class = nil
- c = c + 1
+ else
+ for unicode, d in next, descriptions do
+ local name = d.name
+ if name and lpegmatch(p_crappyname,name) then
+ d.name = nil
+ n = n + 1
+ end
+ if d.class == "base" then
+ d.class = nil
+ c = c + 1
+ end
end
end
- if n > 0 then
- report("%s bogus names removed (verbose unicode)",n)
- end
- if c > 0 then
- report("%s base class tags removed (default is base)",c)
+ if trace_cleanup then
+ if n > 0 then
+ report_cleanup("%s bogus names removed (verbose unicode)",n)
+ end
+ if c > 0 then
+ report_cleanup("%s base class tags removed (default is base)",c)
+ end
end
end
end
+readers.stripredundant = stripredundant
+
function readers.getcomponents(fontdata) -- handy for resolving ligatures when names are missing
local resources = fontdata.resources
if resources then
@@ -813,9 +1028,9 @@ function readers.getcomponents(fontdata) -- handy for resolving ligatures when n
end
for i=1,#steps do
-- we actually had/have this in base mode
- local coverage = steps[i].coverage
- if coverage then
- for k, v in next, coverage do
+ local c = steps[i].coverage
+ if c then
+ for k, v in next, c do
traverse(k,k,v)
end
end
@@ -1251,7 +1466,9 @@ function readers.pack(data)
end
return false
elseif nt >= threshold then
- local one, two, rest = 0, 0, 0
+ local one = 0
+ local two = 0
+ local rest = 0
if pass == 1 then
for k,v in next, c do
if v == 1 then
@@ -2125,17 +2342,24 @@ local function mergesteps_1(lookup,strict)
local f = first.format
for i=2,nofsteps do
if steps[i].format ~= f then
- report("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name)
+ if trace_optimizations then
+ report_optimizations("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name)
+ end
return 0
end
end
end
- report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
+ if trace_optimizations then
+ report_optimizations("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
+ end
local target = first.coverage
for i=2,nofsteps do
- for k, v in next, steps[i].coverage do
- if not target[k] then
- target[k] = v
+ local c = steps[i].coverage
+ if c then
+ for k, v in next, c do
+ if not target[k] then
+ target[k] = v
+ end
end
end
end
@@ -2156,24 +2380,31 @@ local function mergesteps_2(lookup) -- pairs
local f = first.format
for i=2,nofsteps do
if steps[i].format ~= f then
- report("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name)
+ if trace_optimizations then
+ report_optimizations("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name)
+ end
return 0
end
end
end
- report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
+ if trace_optimizations then
+ report_optimizations("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
+ end
local target = first.coverage
for i=2,nofsteps do
- for k, v in next, steps[i].coverage do
- local tk = target[k]
- if tk then
- for kk, vv in next, v do
- if tk[kk] == nil then
- tk[kk] = vv
+ local c = steps[i].coverage
+ if c then
+ for k, v in next, c do
+ local tk = target[k]
+ if tk then
+ for kk, vv in next, v do
+ if tk[kk] == nil then
+ tk[kk] = vv
+ end
end
+ else
+ target[k] = v
end
- else
- target[k] = v
end
end
end
@@ -2189,17 +2420,24 @@ end
local function mergesteps_3(lookup,strict) -- marks
local steps = lookup.steps
local nofsteps = lookup.nofsteps
- report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
+ if trace_optimizations then
+ report_optimizations("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
+ end
-- check first
local coverage = { }
for i=1,nofsteps do
- for k, v in next, steps[i].coverage do
- local tk = coverage[k] -- { class, { x, y } }
- if tk then
- report("quitting merge due to multiple checks")
- return nofsteps
- else
- coverage[k] = v
+ local c = steps[i].coverage
+ if c then
+ for k, v in next, c do
+ local tk = coverage[k] -- { class, { x, y } }
+ if tk then
+ if trace_optimizations then
+ report_optimizations("quitting merge due to multiple checks")
+ end
+ return nofsteps
+ else
+ coverage[k] = v
+ end
end
end
end
@@ -2245,15 +2483,20 @@ local function mergesteps_4(lookup) -- ligatures
local steps = lookup.steps
local nofsteps = lookup.nofsteps
local first = steps[1]
- report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
+ if trace_optimizations then
+ report_optimizations("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
+ end
local target = first.coverage
for i=2,nofsteps do
- for k, v in next, steps[i].coverage do
- local tk = target[k]
- if tk then
- nested(v,tk)
- else
- target[k] = v
+ local c = steps[i].coverage
+ if c then
+ for k, v in next, c do
+ local tk = target[k]
+ if tk then
+ nested(v,tk)
+ else
+ target[k] = v
+ end
end
end
end
@@ -2270,7 +2513,9 @@ local function mergesteps_5(lookup) -- cursive
local steps = lookup.steps
local nofsteps = lookup.nofsteps
local first = steps[1]
- report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
+ if trace_optimizations then
+ report_optimizations("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
+ end
local target = first.coverage
local hash = nil
for k, v in next, target do
@@ -2278,18 +2523,21 @@ local function mergesteps_5(lookup) -- cursive
break
end
for i=2,nofsteps do
- for k, v in next, steps[i].coverage do
- local tk = target[k]
- if tk then
- if not tk[2] then
- tk[2] = v[2]
- end
- if not tk[3] then
- tk[3] = v[3]
+ local c = steps[i].coverage
+ if c then
+ for k, v in next, c do
+ local tk = target[k]
+ if tk then
+ if not tk[2] then
+ tk[2] = v[2]
+ end
+ if not tk[3] then
+ tk[3] = v[3]
+ end
+ else
+ target[k] = v
+ v[1] = hash
end
- else
- target[k] = v
- v[1] = hash
end
end
end
@@ -2319,7 +2567,9 @@ local function checkkerns(lookup)
end
end
if kerns then
- report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name)
+ if trace_optimizations then
+ report_optimizations("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name)
+ end
local c = { }
for g1, d1 in next, coverage do
if d1 and d1 ~= true then
@@ -2379,7 +2629,9 @@ local function checkpairs(lookup)
if step.format == "pair" then
local coverage = onlykerns(step)
if coverage then
- report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name)
+ if trace_optimizations then
+ report_optimizations("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name)
+ end
for g1, d1 in next, coverage do
local d = { }
for g2, d2 in next, d1 do
@@ -2502,17 +2754,19 @@ function readers.compact(data)
end
end
end
- else
- report("no lookups in %a",what)
+ elseif trace_optimizations then
+ report_optimizations("no lookups in %a",what)
end
end
compact("sequences")
compact("sublookups")
- if merged > 0 then
- report("%i steps of %i removed due to merging",merged,allsteps)
- end
- if kerned > 0 then
- report("%i steps of %i steps turned from pairs into kerns",kerned,allsteps)
+ if trace_optimizations then
+ if merged > 0 then
+ report_optimizations("%i steps of %i removed due to merging",merged,allsteps)
+ end
+ if kerned > 0 then
+ report_optimizations("%i steps of %i steps turned from pairs into kerns",kerned,allsteps)
+ end
end
end
@@ -2612,7 +2866,7 @@ function readers.expand(data)
-- or bb?
d.width = defaultwidth
elseif trace_markwidth and wd ~= 0 and d.class == "mark" then
- report("mark %a with width %b found in %a",d.name or "<noname>",wd,basename)
+ report_markwidth("mark %a with width %b found in %a",d.name or "<noname>",wd,basename)
end
if bb then
local ht = bb[4]
diff --git a/tex/context/base/mkiv/font-pre.mkiv b/tex/context/base/mkiv/font-pre.mkiv
index b49bc560e..c1c24b854 100644
--- a/tex/context/base/mkiv/font-pre.mkiv
+++ b/tex/context/base/mkiv/font-pre.mkiv
@@ -53,10 +53,7 @@
script=auto, % on speed; 'base' just doesn't play well with dynamics; some day we can even
autoscript=position,
autolanguage=position,
-% ccmp=yes,
kern=yes, % consider skipping the base passes when no base mode is used
-% palt=yes,
-% pwid=yes,
mark=yes,
mkmk=yes,
curs=yes]
@@ -323,6 +320,22 @@
\definefontfeature [tamil-two] [tamil-one] [script=tml2]
\definefontfeature [telugu-two] [telugu-one] [script=tel2]
+% tibetan
+
+\definefontfeature
+ [tibetan]
+ [always]
+ [script=tibt,
+ language=dflt,
+ locl=yes,
+ ccmp=yes,
+ abvs=yes,
+ blws=yes,
+ calt=yes,
+ liga=yes,
+ abvm=yes,
+ blwm=yes]
+
% cjk
\definefontfeature
@@ -452,9 +465,37 @@
[slanted]
[slant=.2]
+% \definefontfeature
+% [boldened]
+% [extend=1.2]
+
+%D Neat:
+
+% By eye:
+%
+% \definefontfeature[boldened-10][effect={width=0.10,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.125,extend=1.025,squeeze=0.99250}]
+% \definefontfeature[boldened-15][effect={width=0.15,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.250,extend=1.050,squeeze=0.98750}]
+% \definefontfeature[boldened-20][effect={width=0.20,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.375,extend=1.075,squeeze=0.98125}]
+% \definefontfeature[boldened-30][effect={width=0.30,delta=1.0,hdelta=0.500,ddelta=0.150,vshift=0.500,extend=1.100,squeeze=0.97500}]
+%
+% By calculation:
+%
+% \definefontfeature[boldened-10][effect={width=0.10,delta=1.0,hdelta=0.02500,ddelta=0.02500,vshift=0.02500,extend=1.050,squeeze=0.99500}]
+% \definefontfeature[boldened-15][effect={width=0.15,delta=1.0,hdelta=0.05625,ddelta=0.05625,vshift=0.05625,extend=1.075,squeeze=0.99250}]
+% \definefontfeature[boldened-20][effect={width=0.20,delta=1.0,hdelta=0.10000,ddelta=0.10000,vshift=0.10000,extend=1.100,squeeze=0.99000}]
+% \definefontfeature[boldened-30][effect={width=0.30,delta=1.0,hdelta=0.22500,ddelta=0.22500,vshift=0.22500,extend=1.150,squeeze=0.98500}]
+%
+% So we can do this:
+
+\definefontfeature[boldened-10][effect={width=0.10,auto=yes}]
+\definefontfeature[boldened-15][effect={width=0.15,auto=yes}]
+\definefontfeature[boldened-20][effect={width=0.20,auto=yes}]
+\definefontfeature[boldened-25][effect={width=0.25,auto=yes}]
+\definefontfeature[boldened-30][effect={width=0.30,auto=yes}]
+
\definefontfeature
[boldened]
- [extend=1.2]
+ [boldened-30]
%D Emoji:
diff --git a/tex/context/base/mkiv/font-prv.lua b/tex/context/base/mkiv/font-prv.lua
new file mode 100644
index 000000000..20c06d2e5
--- /dev/null
+++ b/tex/context/base/mkiv/font-prv.lua
@@ -0,0 +1,78 @@
+if not modules then modules = { } end modules ['font-prv'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type = type
+local formatters = string.formatters
+
+local fonts = fonts
+local helpers = fonts.helpers
+local fontdata = fonts.hashes.identifiers
+
+local setmetatableindex = table.setmetatableindex
+
+local currentprivate = fonts.privateoffsets.textextrabase
+local maximumprivate = currentprivate + 0xFFF
+
+local extraprivates = { }
+helpers.extraprivates = extraprivates
+
+function fonts.helpers.addextraprivate(name,f)
+ extraprivates[#extraprivates+1] = { name, f }
+end
+
+-- if we run out of space we can think of another range but by sharing we can
+-- use these privates for mechanisms like alignments-on-character and such
+
+local sharedprivates = setmetatableindex(function(t,k)
+ local v = currentprivate
+ if currentprivate < maximumprivate then
+ currentprivate = currentprivate + 1
+ else
+ -- reuse last slot, todo: warning
+ end
+ t[k] = v
+ return v
+end)
+
+function helpers.addprivate(tfmdata,name,characterdata)
+ local properties = tfmdata.properties
+ local characters = tfmdata.characters
+ local privates = properties.privates
+ if not privates then
+ privates = { }
+ properties.privates = privates
+ end
+ if not name then
+ name = formatters["anonymous_private_0x%05X"](currentprivate)
+ end
+ local usedprivate = sharedprivates[name]
+ privates[name] = usedprivate
+ characters[usedprivate] = characterdata
+ return usedprivate
+end
+
+function helpers.getprivates(tfmdata)
+ if type(tfmdata) == "number" then
+ tfmdata = fontdata[tfmdata]
+ end
+ local properties = tfmdata.properties
+ return properties and properties.privates
+end
+
+function helpers.hasprivate(tfmdata,name)
+ if type(tfmdata) == "number" then
+ tfmdata = fontdata[tfmdata]
+ end
+ local properties = tfmdata.properties
+ local privates = properties and properties.privates
+ return privates and privates[name] or false
+end
+
+function helpers.privateslot(name)
+ return rawget(sharedprivates,name)
+end
diff --git a/tex/context/base/mkiv/font-sel.lua b/tex/context/base/mkiv/font-sel.lua
index e7f56047b..15d3838f6 100644
--- a/tex/context/base/mkiv/font-sel.lua
+++ b/tex/context/base/mkiv/font-sel.lua
@@ -232,52 +232,6 @@ local m_alternative = {
["sc"] = "smallcaps"
}
---~ methods["style"] = function(data,alternative,style)
---~ local family = data.metadata.family
---~ local style = m_alternative[style] or style
---~ if trace_alternatives then
---~ report_selectfont("Alternative '%s': Using method 'style' with argument '%s'",alternative,style)
---~ end
---~ local fontweight = m_name[style] and m_name[style]["weight"] or "regular"
---~ local fontstyle = m_name[style] and m_name[style]["style"] or "normal"
---~ local fontwidth = m_name[style] and m_name[style]["width"] or "normal"
---~ local pattern = getlookups{
---~ familyname = cleanname(family),
---~ pfmweight = m_weight[fontweight],
---~ style = fontstyle
---~ }
---~ if #pattern == 1 then
---~ selectfont_savefile(data,alternative,0,"default",pattern[1])
---~ elseif #pattern > 1 then
---~ local bodyfontsize, minsize, maxsize, width = nil, nil, nil, nil
---~ for patternindex, patternentry in next, pattern do
---~ minsize = patternentry["minsize"]
---~ maxsize = patternentry["maxsize"]
---~ width = patternentry["pfmwidth"]
---~ if minsize and maxsize then
---~ for fontsize, fontstate in next, bodyfontsizes do
---~ bodyfontsize, _ = number.splitdimen(fontsize)
---~ bodyfontsize = bodyfontsize * 10
---~ if minsize < bodyfontsize and bodyfontsize < maxsize then
---~ if bodyfontsize == 100 then
---~ selectfont_savefile(data,alternative,0,"default",patternentry)
---~ end
---~ selectfont_savefile(data,alternative,bodyfontsize,fontsize,patternentry)
---~ end
---~ end
---~ else
---~ if width == m_width[fontwidth] then
---~ selectfont_savefile(data,alternative,0,"default",patternentry)
---~ end
---~ end
---~ end
---~ else
---~ if trace_alternatives then
---~ report_selectfont("Alternative '%s': No font was found for the requested style '%s' from '%s'",alternative,style,family)
---~ end
---~ end
---~ end
-
local function m_style_family(family)
local askedname = cleanname(family)
local familyname = getlookups{ familyname = askedname }
@@ -348,7 +302,7 @@ local function m_style_style(entries,style)
if style == "italic" and entry["angle"] and entry["angle"] ~= 0 then
t[#t+1] = entry
elseif style == "normal" and entry["angle"] and entry["angle"] ~= 0 then
- --~ Fix needed for fonts with wrong value for the style field
+ -- Fix needed for fonts with wrong value for the style field
elseif entry["style"] == style then
t[#t+1] = entry
end
@@ -448,10 +402,10 @@ methods[v_default] = function(data,alternative)
report_selectfont("Alternative '%s': The family '%s' contains only one font",alternative,family)
end
selectfont_savefile(data,alternative,0,"default",result[1])
- --~ if trace_alternatives then
- --~ report_selectfont("Alternative '%s': Changing method 'default' to method 'style'",alternative)
- --~ end
- --~ methods["file"](data,alternative,result[1]["filename"])
+ -- if trace_alternatives then
+ -- report_selectfont("Alternative '%s': Changing method 'default' to method 'style'",alternative)
+ -- end
+ -- methods["file"](data,alternative,result[1]["filename"])
else
if trace_alternatives then
report_selectfont("Alternative '%s': Changing method 'default' to method 'style'",alternative)
@@ -499,38 +453,6 @@ function selectfont.userdata(index)
end
end
---~ function selectfont.registerfiles(index)
---~ local data = data[index]
---~ local colon = splitat(":",true)
---~ for alternative, _ in next, alternatives do
---~ local arguments = data.alternatives[alternative]
---~ if arguments ~= "" then
---~ local entries = settings_to_array(arguments)
---~ local setmethod = false
---~ for index, entry in next, entries do
---~ method, argument = lpegmatch(colon,entry)
---~ if not argument then
---~ argument = method
---~ method = "name"
---~ end
---~ if extras[method] then
---~ extras[method](data,alternative,argument)
---~ elseif methods[method] then
---~ if not setmethod then
---~ setmethod = true
---~ methods[method](data,alternative,argument)
---~ end
---~ end
---~ end
---~ if not setmethod then
---~ methods[v_default](data,alternative)
---~ end
---~ else
---~ methods[v_default](data,alternative)
---~ end
---~ end
---~ end
-
function selectfont.registerfiles(index)
local data = data[index]
local colon = splitat(":",true)
@@ -662,8 +584,8 @@ function selectfont.fontsynonym(data,class,style,alternative,index)
local fontsizes = sortedkeys(fontfiles)
local fallback = index ~= 0
local fontclass = lower(class)
- --~ local fontfeature = data.features and data.features[alternative] or data.options.features
- --~ local fontgoodie = data.goodies and data.goodies [alternative] or data.options.goodies
+ --local fontfeature = data.features and data.features[alternative] or data.options.features
+ --local fontgoodie = data.goodies and data.goodies [alternative] or data.options.goodies
local fontfeature = selectfont.features(data,style,alternative)
local fontgoodie = selectfont.goodies (data,style,alternative)
local synonym = m_synonym[style] and m_synonym[style][alternative]
@@ -675,25 +597,25 @@ function selectfont.fontsynonym(data,class,style,alternative,index)
end
local fontfallback = formatters["fallback-%s-%s-%s"](fontclass,style,alternative)
for _, fontsize in next, fontsizes do
- --~ if trace_typescript then
- --~ report_typescript("Synonym: '%s', Size: '%s', File: '%s'",fontfile,fontfiles[fontsize][1],fontfiles[fontsize][2])
- --~ end
+ -- if trace_typescript then
+ -- report_typescript("Synonym: '%s', Size: '%s', File: '%s'",fontfile,fontfiles[fontsize][1],fontfiles[fontsize][2])
+ -- end
registerdesignsizes(fontfile,fontfiles[fontsize][1],fontfiles[fontsize][2])
end
if fallback then
- --~ if trace_typescript then
- --~ report_typescript("Synonym: '%s', File: '%s', Features: '%s'",fontsynonym,fontfile,fontfeature)
- --~ end
+ -- if trace_typescript then
+ -- report_typescript("Synonym: '%s', File: '%s', Features: '%s'",fontsynonym,fontfile,fontfeature)
+ -- end
ctx_definefontsynonym( { fontsynonym }, { fontfile }, { features = fontfeature } )
else
- --~ if trace_typescript then
- --~ report_typescript("Synonym: '%s', File: '%s', Features: '%s', Goodies: '%s', Fallbacks: '%s'",fontsynonym,fontfile,fontfeature,fontgoodie,fontfallback)
- --~ end
+ -- if trace_typescript then
+ -- report_typescript("Synonym: '%s', File: '%s', Features: '%s', Goodies: '%s', Fallbacks: '%s'",fontsynonym,fontfile,fontfeature,fontgoodie,fontfallback)
+ -- end
ctx_definefontsynonym( { fontsynonym }, { fontfile }, { features = fontfeature, goodies = fontgoodie, fallbacks = fontfallback } )
if synonym then
- --~ if trace_typescript then
- --~ report_typescript("Synonym: '%s', File: '%s'",synonym,fontsynonym)
- --~ end
+ -- if trace_typescript then
+ -- report_typescript("Synonym: '%s', File: '%s'",synonym,fontsynonym)
+ -- end
ctx_definefontsynonym( { synonym }, { fontsynonym } )
end
end
@@ -711,9 +633,9 @@ function selectfont.fontfallback(data,class,style,alternative,index)
if index == 1 then
ctx_resetfontfallback( { fontfallback } )
end
- --~ if trace_typescript then
- --~ report_typescript("Fallback: '%s', Synonym: '%s', Range: '%s', Scale: '%s', Check: '%s', Force: '%s'",fontfallback,fontsynonym,range,scale,check,force)
- --~ end
+ -- if trace_typescript then
+ -- report_typescript("Fallback: '%s', Synonym: '%s', Range: '%s', Scale: '%s', Check: '%s', Force: '%s'",fontfallback,fontsynonym,range,scale,check,force)
+ -- end
ctx_definefontfallback( { fontfallback }, { fontsynonym }, { range }, { rscale = scale, check = check, force = force } )
end
@@ -730,9 +652,9 @@ function selectfont.filefallback(data,class,style,alternative,index)
if index == 1 then
ctx_resetfontfallback( { fontfallback } )
end
- --~ if trace_typescript then
- --~ report_typescript("Fallback: '%s', File: '%s', Features: '%s', Range: '%s', Scale: '%s', Check: '%s', Force: '%s', Offset: '%s'",fontfallback,fontfile[2],fontfeature,range,scale,check,force,offset)
- --~ end
+ -- if trace_typescript then
+ -- report_typescript("Fallback: '%s', File: '%s', Features: '%s', Range: '%s', Scale: '%s', Check: '%s', Force: '%s', Offset: '%s'",fontfallback,fontfile[2],fontfeature,range,scale,check,force,offset)
+ -- end
ctx_definefontfallback( { fontfallback }, { formatters["file:%s*%s"](fontfile[2],fontfeature) }, { range }, { rscale = scale, check = check, force = force, offset = offset } )
end
@@ -763,9 +685,9 @@ function selectfont.fallback(data)
local fallbacks = fallbacks[fontclass] and fallbacks[fontclass][fontstyle]
if fallbacks then
for index, entry in next, fallbacks do
- --~ I need different fallback routines for math and text because
- --~ font synonyms can’t be used with math fonts and I have to apply
- --~ feature settings with the \definefontfallback command.
+ -- I need different fallback routines for math and text because
+ -- font synonyms can’t be used with math fonts and I have to apply
+ -- feature settings with the \definefontfallback command.
if fontstyle == "mm" then
selectfont.mathfallback(index,entry,fontclass,fontstyle)
else
@@ -792,7 +714,8 @@ function selectfont.typescript(data)
end
end
for alternative, _ in next, alternatives do
- if style == "mm" then -- Set math fonts only for upright and bold alternatives
+ if style == "mm" then
+ -- Set math fonts only for upright and bold alternatives
if alternative == "tf" or alternative == "bf" then
selectfont.fontsynonym (data,class,style,alternative,0)
end
@@ -813,9 +736,9 @@ function selectfont.bodyfont(data)
for alternative, _ in next, alternatives do
fontsynonym = formatters["synonym-%s-%s-%s"](fontclass,fontstyle,alternative)
fontlist[#fontlist+1] = formatters["%s=%s sa 1"] (alternative,fontsynonym)
- --~ if trace_typescript then
- --~ report_typescript("Alternative '%s': Synonym '%s'",alternative,fontsynonym)
- --~ end
+ -- if trace_typescript then
+ -- report_typescript("Alternative '%s': Synonym '%s'",alternative,fontsynonym)
+ -- end
end
fontlist = concat(fontlist,",")
ctx_definebodyfont( { class }, { fontsizes }, { fontstyle }, { fontlist } )
@@ -836,9 +759,9 @@ function selectfont.typeface(data)
local style = m_style[fontstyle]
local size = data.options.designsize ~= "" and data.options.designsize or "default"
local scale = data.options.rscale ~= "" and data.options.rscale or 1
- --~ if trace_typescript then
- --~ report_typescript("Class: '%s', Style: '%s', Size: '%s', Scale: '%s'",fontclass,fontstyle,size,scale)
- --~ end
+ -- if trace_typescript then
+ -- report_typescript("Class: '%s', Style: '%s', Size: '%s', Scale: '%s'",fontclass,fontstyle,size,scale)
+ -- end
ctx_definetypeface( { fontclass }, { fontstyle }, { style }, { "" }, { "default" }, { designsize = size, rscale = scale } )
end
diff --git a/tex/context/base/mkiv/font-set.mkvi b/tex/context/base/mkiv/font-set.mkvi
index 2c6d065d8..aac83e1aa 100644
--- a/tex/context/base/mkiv/font-set.mkvi
+++ b/tex/context/base/mkiv/font-set.mkvi
@@ -46,7 +46,7 @@
% \def\font_preloads_reset_nullfont % this is needed because some macro packages (tikz) misuse \nullfont
% {\dorecurse\plusseven{\fontdimen\recurselevel\nullfont\zeropoint}% keep en eye on this as:
% \clf_resetnullfont % in luatex 0.70 this will also do the previous
-% \globallet\font_preloads_reset_nullfont\relax}
+% \glet\font_preloads_reset_nullfont\relax}
\def\font_preload_check_mode
{\doifelsemode{lmmath}
@@ -122,14 +122,14 @@
\font_preloads_reset
\else
\font_preloads_reset
- \pushmacro\fontstyle
+ \push_macro_fontstyle
\ifcsname\??fontclass\fontclass\s!mm\s!features\endcsname \else
\font_preload_default_fonts_mm
\fi
\ifcsname\??fontclass\fontclass\s!tt\s!features\endcsname \else
\font_preload_default_fonts_tt
\fi
- \popmacro\fontstyle
+ \pop_macro_fontstyle
\font_preloads_reset_checked % reset third, mm and tt
\setupbodyfont[\fontstyle]%
\fi}
diff --git a/tex/context/base/mkiv/font-shp.lua b/tex/context/base/mkiv/font-shp.lua
index 75a12ac82..d5c194c85 100644
--- a/tex/context/base/mkiv/font-shp.lua
+++ b/tex/context/base/mkiv/font-shp.lua
@@ -12,6 +12,7 @@ local formatters = string.formatters
local otf = fonts.handlers.otf
local afm = fonts.handlers.afm
+local pfb = fonts.handlers.pfb
local hashes = fonts.hashes
local identifiers = hashes.identifiers
@@ -39,7 +40,8 @@ local function packoutlines(data,makesequence)
return
end
if makesequence then
- for index=1,#glyphs do
+-- for index=1,#glyphs do
+ for index=0,#glyphs-1 do
local glyph = glyphs[index]
local segments = glyph.segments
if segments then
@@ -48,6 +50,7 @@ local function packoutlines(data,makesequence)
for i=1,#segments do
local segment = segments[i]
local nofsegment = #segment
+ -- why last first ... needs documenting
nofsequence = nofsequence + 1
sequence[nofsequence] = segment[nofsegment]
for i=1,nofsegment-1 do
@@ -64,7 +67,8 @@ local function packoutlines(data,makesequence)
local common = { }
local reverse = { }
local last = 0
- for index=1,#glyphs do
+-- for index=1,#glyphs do
+ for index=0,#glyphs-1 do
local segments = glyphs[index].segments
if segments then
for i=1,#segments do
@@ -73,7 +77,8 @@ local function packoutlines(data,makesequence)
end
end
end
- for index=1,#glyphs do
+-- for index=1,#glyphs do
+ for index=0,#glyphs-1 do
local segments = glyphs[index].segments
if segments then
for i=1,#segments do
@@ -114,7 +119,8 @@ local function unpackoutlines(data)
if not glyphs then
return
end
- for index=1,#glyphs do
+-- for index=1,#glyphs do
+ for index=0,#glyphs-1 do
local segments = glyphs[index].segments
if segments then
for i=1,#segments do
@@ -131,7 +137,7 @@ end
-- todo: loaders per format
local readers = otf.readers
-local cleanname = readers.helpers.cleanname
+local cleanname = otf.readers.helpers.cleanname
local function makehash(filename,sub,instance)
local name = cleanname(file.basename(filename))
@@ -157,7 +163,7 @@ local function loadoutlines(cache,filename,sub,instance)
local hash = makehash(filename,sub,instance)
data = containers.read(cache,hash)
if not data or data.time ~= time or data.size ~= size then
- data = readers.loadshapes(filename,sub,instance)
+ data = otf.readers.loadshapes(filename,sub,instance)
if data then
data.size = size
data.format = data.format or (kind == "otf" and "opentype") or "truetype"
@@ -204,19 +210,16 @@ local function loadstreams(cache,filename,sub,instance)
local size = attr and attr.size or 0
local time = attr and attr.modification or 0
local sub = tonumber(sub)
-
- -- fonts.formats
-
if size > 0 and (kind == "otf" or kind == "ttf" or kind == "tcc") then
local hash = makehash(filename,sub,instance)
data = containers.read(cache,hash)
if not data or data.time ~= time or data.size ~= size then
- data = readers.loadshapes(filename,sub,instance,true)
+ data = otf.readers.loadshapes(filename,sub,instance,true)
if data then
local glyphs = data.glyphs
local streams = { }
if glyphs then
- for i=0,#glyphs do
+ for i=0,#glyphs-1 do
streams[i] = glyphs[i].stream or ""
end
end
@@ -229,13 +232,68 @@ local function loadstreams(cache,filename,sub,instance)
data = containers.read(cache,hash) -- frees old mem
end
end
+ elseif size > 0 and (kind == "pfb") then
+ local hash = makehash(filename,sub,instance)
+ data = containers.read(cache,hash)
+ if not data or data.time ~= time or data.size ~= size then
+ local names, encoding, streams, metadata = pfb.loadvector(filename,false,true)
+ if streams then
+ local fontbbox = metadata.fontbbox or { 0, 0, 0, 0 }
+ for i=0,#streams do
+ streams[i] = streams[i].stream or "\14"
+ end
+ data = {
+ filename = filename,
+ size = size,
+ time = time,
+ format = "type1",
+ streams = streams,
+ fontheader = {
+ fontversion = metadata.version,
+ units = 1000, -- can this be different?
+ xmin = fontbbox[1],
+ ymin = fontbbox[2],
+ xmax = fontbbox[3],
+ ymax = fontbbox[4],
+ },
+ horizontalheader = {
+ ascender = 0,
+ descender = 0,
+ },
+ maximumprofile = {
+ nofglyphs = #streams + 1,
+ },
+ names = {
+ copyright = metadata.copyright,
+ family = metadata.familyname,
+ fullname = metadata.fullname,
+ fontname = metadata.fontname,
+ subfamily = metadata.subfamilyname,
+ trademark = metadata.trademark,
+ notice = metadata.notice,
+ version = metadata.version,
+ },
+ cffinfo = {
+ familyname = metadata.familyname,
+ fullname = metadata.fullname,
+ italicangle = metadata.italicangle,
+ monospaced = metadata.isfixedpitch and true or false,
+ underlineposition = metadata.underlineposition,
+ underlinethickness = metadata.underlinethickness,
+ weight = metadata.weight,
+ },
+ }
+ containers.write(cache,hash,data)
+ data = containers.read(cache,hash) -- frees old mem
+ end
+ end
else
data = {
filename = filename,
size = 0,
time = time,
format = "unknown",
- glyphs = { }
+ streams = { }
}
end
return data
@@ -265,7 +323,15 @@ hashes.shapes = table.setmetatableindex(function(t,k)
end
end)
-local function loadstreamdata(fontdata,streams)
+local function getstreamhash(fontid)
+ local fontdata = identifiers[fontid]
+ if fontdata then
+ local properties = fontdata.properties
+ return makehash(properties.filename,fontdata.subindex,properties.instance)
+ end
+end
+
+local function loadstreamdata(fontdata)
local properties = fontdata.properties
local filename = properties.filename
local subindex = fontdata.subindex
@@ -289,12 +355,19 @@ end)
otf.loadoutlinedata = loadoutlinedata -- not public
otf.loadstreamdata = loadstreamdata -- not public
otf.loadshapes = loadshapes
+otf.getstreamhash = getstreamhash -- not public, might move to other namespace
--- experimental code, for me only ... unsupported
+-- experimental code, for me only ... unsupported (todo: use %N)
-local f_c = string.formatters["%F %F %F %F %F %F c"]
-local f_l = string.formatters["%F %F l"]
-local f_m = string.formatters["%F %F m"]
+local f_c = formatters["%F %F %F %F %F %F c"]
+local f_l = formatters["%F %F l"]
+local f_m = formatters["%F %F m"]
+
+directives.register("pdf.stripzeros",function()
+ f_c = formatters["%N %N %N %N %N %N c"]
+ f_l = formatters["%N %N l"]
+ f_m = formatters["%N %N m"]
+end)
local function segmentstopdf(segments,factor,bt,et)
local t = { }
@@ -316,9 +389,12 @@ local function segmentstopdf(segments,factor,bt,et)
elseif w == "q" then
local p = segments[i-1]
local n = #p
- local l_x, l_y = factor*p[n-2], factor*p[n-1]
- local m_x, m_y = factor*s[1], factor*s[2]
- local r_x, r_y = factor*s[3], factor*s[4]
+ local l_x = factor*p[n-2]
+ local l_y = factor*p[n-1]
+ local m_x = factor*s[1]
+ local m_y = factor*s[2]
+ local r_x = factor*s[3]
+ local r_y = factor*s[4]
m = m + 1
t[m] = f_c (
l_x + 2/3 * (m_x-l_x), l_y + 2/3 * (m_y-l_y),
@@ -338,7 +414,7 @@ local function segmentstopdf(segments,factor,bt,et)
end
end
-local function addvariableshapes(tfmdata,key,value)
+local function initialize(tfmdata,key,value)
if value then
local shapes = otf.loadoutlinedata(tfmdata)
if not shapes then
@@ -354,7 +430,9 @@ local function addvariableshapes(tfmdata,key,value)
local factor = hfactor / 65536
local getactualtext = otf.getactualtext
for unicode, char in next, characters do
- if not char.commands then
+ if char.commands then
+ -- can't happen as we're doing this before other messing around
+ else
local shape = glyphs[char.index]
if shape then
local segments = shape.segments
@@ -375,12 +453,12 @@ otf.features.register {
name = "variableshapes", -- enforced for now
description = "variable shapes",
manipulators = {
- base = addvariableshapes,
- node = addvariableshapes,
+ base = initialize,
+ node = initialize,
}
}
--- In the end it is easier to just provide the new charstring (cff) and points (ttdf). First
+-- In the end it is easier to just provide the new charstring (cff) and points (ttf). First
-- of all we already have the right information so there is no need to patch the already complex
-- backend code (we only need to make sure the cff is valid). Also, I prototyped support for
-- these fonts using (converted to) normal postscript shapes, a functionality that was already
diff --git a/tex/context/base/mkiv/font-sol.lua b/tex/context/base/mkiv/font-sol.lua
index 8967d88e6..002f9df13 100644
--- a/tex/context/base/mkiv/font-sol.lua
+++ b/tex/context/base/mkiv/font-sol.lua
@@ -54,8 +54,6 @@ local settings_to_hash = utilities.parsers.settings_to_hash
local tasks = nodes.tasks
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local getfield = nuts.getfield
local getnext = nuts.getnext
@@ -65,8 +63,10 @@ local getattr = nuts.getattr
local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
local getlist = nuts.getlist
-local getdir = nuts.getdir
+local getdirection = nuts.getdirection
local getwidth = nuts.getwidth
+local getdata = nuts.getdata
+
local getboxglue = nuts.getboxglue
local setattr = nuts.setattr
@@ -78,13 +78,15 @@ local find_node_tail = nuts.tail
local flush_node = nuts.flush_node
local flush_node_list = nuts.flush_list
local copy_node_list = nuts.copy_list
-local traverse_nodes = nuts.traverse
-local traverse_ids = nuts.traverse_id
local hpack_nodes = nuts.hpack
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
local protect_glyphs = nuts.protect_glyphs
+local nextnode = nuts.traversers.next
+local nexthlist = nuts.traversers.hlist
+local nextwhatsit = nuts.traversers.whatsit
+
local repack_hlist = nuts.repackhlist
local nodes_to_utf = nodes.listtoutf
@@ -108,13 +110,15 @@ local whatsit_code = nodecodes.whatsit
local fontkern_code = kerncodes.fontkern
-local userdefined_code = whatsitcodes.userdefined
+local userdefinedwhatsit_code = whatsitcodes.userdefined
+
+local nodeproperties = nodes.properties.data
local nodepool = nuts.pool
local usernodeids = nodepool.userids
-local new_textdir = nodepool.textdir
-local new_usernumber = nodepool.usernumber
+local new_direction = nodepool.direction
+local new_usernode = nodepool.usernode
local new_glue = nodepool.glue
local new_leftskip = nodepool.leftskip
@@ -237,7 +241,6 @@ local function convert(featuresets,name,list)
fs = contextsetups[feature]
fn = fs and fs.number
end
--- inspect(fs)
if fn then
nofnumbers = nofnumbers + 1
numbers[nofnumbers] = fn
@@ -344,20 +347,23 @@ directives.register("builders.paragraphs.solutions.splitters.encapsulate", funct
encapsulate = v
end)
-function splitters.split(head)
- -- quite fast
- head = tonut(head)
- local current, done, rlmode, start, stop, attribute = head, false, false, nil, nil, 0
- cache, max_less, max_more = { }, 0, 0
+function splitters.split(head) -- best also pass the direction
+ local current = head
+ local r2l = false
+ local start = nil
+ local stop = nil
+ local attribute = 0
+ cache = { }
+ max_less = 0
+ max_more = 0
local function flush() -- we can move this
local font = getfont(start)
local last = getnext(stop)
--- local list = last and copy_node_list(start,last) or copy_node_list(start)
- local list = last and copy_node_list(start,stop) or copy_node_list(start)
- local n = #cache + 1
+ local list = last and copy_node_list(start,last) or copy_node_list(start)
+ local n = #cache + 1
if encapsulate then
- local user_one = new_usernumber(splitter_one,n)
- local user_two = new_usernumber(splitter_two,n)
+ local user_one = new_usernode(splitter_one,n)
+ local user_two = new_usernode(splitter_two,n)
head, start = insert_node_before(head,start,user_one)
insert_node_after(head,stop,user_two)
else
@@ -371,9 +377,8 @@ function splitters.split(head)
end
end
end
- local r2l = rlmode == "TRT" or rlmode == "+TRT"
if r2l then
- local dirnode = new_textdir("+TRT")
+ local dirnode = new_direction(righttoleft) -- brrr, we don't pop ... to be done (when used at all)
setlink(dirnode,list)
list = dirnode
end
@@ -393,7 +398,7 @@ function splitters.split(head)
local m = #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
+ start, stop = nil, nil
end
while current do -- also ischar
local next = getnext(current)
@@ -422,11 +427,19 @@ function splitters.split(head)
else
start, stop = nil, nil
end
- elseif id == dir_code or id == localpar_code then
+ elseif id == dir_code then
+ -- not tested (to be done by idris when font is ready)
if start then
flush()
end
- rlmode = getdir(current)
+ local direction, pop = getdirection(current)
+ r2l = not pop and direction == righttoleft
+ elseif id == localpar_code and getsubtype(current) == 0 then
+ if start then
+ flush() -- very unlikely as this starts a paragraph
+ end
+ local direction = getdirection(current)
+ r2l = direction == righttoleft or direction == "TRT" -- for old times sake
else
if start then
flush()
@@ -438,31 +451,37 @@ function splitters.split(head)
flush()
end
nofparagraphs = nofparagraphs + 1
- nofwords = nofwords + #cache
- return tonode(head), done
+ nofwords = nofwords + #cache
+ return head
end
local function collect_words(list) -- can be made faster for attributes
- local words, w, word = { }, 0, nil
+ local words = { }
+ local w = 0
+ local word = nil
if encapsulate then
- for current in traverse_ids(whatsit_code,list) do
- if getsubtype(current) == userdefined_code then -- hm
- local user_id = getfield(current,"user_id")
- if user_id == splitter_one then
- word = { getfield(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
+ for current, subtype in nextwhatsit, list do
+ if subtype == userdefinedwhatsit_code then -- hm
+ local p = nodeproperties[current]
+ if p then
+ local user_id = p.id
+ if user_id == splitter_one then
+ word = { p.data, 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
end
else
- local current, first, last, index = list, nil, nil, nil
+ local first, last, index
+ local current = list
while current do
-- todo: disc and kern
local id = getid(current)
@@ -527,7 +546,9 @@ local function collect_words(list) -- can be made faster for attributes
if trace_split then
for i=1,#words do
local w = words[i]
- local n, f, l = w[1], w[2], w[3]
+ local n = w[1]
+ local f = w[2]
+ local l = w[3]
local c = cache[n]
if c then
report_splitters("found %4i: word %a, cached %a",n,nodes_to_utf(f,true,true,l),nodes_to_utf(c.original,true))
@@ -584,21 +605,20 @@ local function doit(word,list,best,width,badness,line,set,listdir)
noftries = noftries + 1
local first = copy_node_list(original)
if not trace_colors then
- for n in traverse_nodes(first) do -- maybe fast force so no attr needed
+ for n in nextnode, first do -- maybe fast force so no attr needed
setattr(n,0,featurenumber) -- this forces dynamics
end
elseif set == "less" then
- for n in traverse_nodes(first) do
+ for n in nextnode, first do
setnodecolor(n,"font:isol") -- yellow
setattr(n,0,featurenumber)
end
else
- for n in traverse_nodes(first) do
+ for n in nextnode, first do
setnodecolor(n,"font:medi") -- green
setattr(n,0,featurenumber)
end
end
-first = tonode(first)
local font = found.font
local setdynamics = setfontdynamics[font]
if setdynamics then
@@ -610,7 +630,6 @@ first = tonode(first)
report_solutions("fatal error, no dynamics for font %a",font)
end
first = inject_kerns(first)
-first = tonut(first)
if getid(first) == whatsit_code then
local temp = first
first = getnext(first)
@@ -753,19 +772,19 @@ function splitters.optimize(head)
if trace_optimize then
report_optimizers("preroll %a, variant %a, criterium %a, cache size %a",preroll,variant,criterium,nc)
end
- for current in traverse_ids(hlist_code,tonut(head)) do
+ for current in nexthlist, head do
line = line + 1
- local sign = getfield(current,"glue_sign")
- local dir = getdir(current)
- local width = getwidth(current)
- local list = getlist(current)
+ local sign = getfield(current,"glue_sign")
+ local direction = getdirection(current)
+ local width = getwidth(current)
+ local list = getlist(current)
if not encapsulate and getid(list) == glyph_code then
-- nasty .. we always assume a prev being there .. future luatex will always have a leftskip set
-- is this assignment ok ? .. needs checking
list = insert_node_before(list,list,new_leftskip(0)) -- new_glue(0)
setlist(current,list)
end
- local temp, badness = repack_hlist(list,width,'exactly',dir) -- it would be nice if the badness was stored in the node
+ local temp, badness = repack_hlist(list,width,"exactly",direction) -- it would be nice if the badness was stored in the node
if badness > 0 then
if sign == 0 then
if trace_optimize then
@@ -785,7 +804,8 @@ function splitters.optimize(head)
set, max = "less", max_less
end
-- we can keep the best variants
- local lastbest, lastbadness = nil, badness
+ local lastbest = nil
+ local lastbadness = badness
if preroll then
local bb, base
for i=1,max do
@@ -858,7 +878,7 @@ 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",
+ return format("%s words identified in %s paragraphs, %s words retried, %s lines tried, %s seconds used, %s adapted, %0.1f lines per second",
nofwords,nofparagraphs,noftries,nofadapted+nofkept,elapsed,nofadapted,average)
end
end)
diff --git a/tex/context/base/mkiv/font-sty.mkvi b/tex/context/base/mkiv/font-sty.mkvi
index 2d00c5ec8..8200aa957 100644
--- a/tex/context/base/mkiv/font-sty.mkvi
+++ b/tex/context/base/mkiv/font-sty.mkvi
@@ -59,17 +59,17 @@
\newconstant\c_fonts_basics_alternative_style_method
\def\font_basics_define_alternative_style_indeed#variantone#varianttwo#command%
- {\setvalue{\??alternativestyle#command}{\font_helpers_apply_alternative_style{#variantone}{#varianttwo}}%
+ {\setuvalue{\??alternativestyle#command}{\font_helpers_apply_alternative_style{#variantone}{#varianttwo}}%
\ifcsname#command\endcsname
% no redefinition
\else\ifnum\c_fonts_basics_alternative_style_method=\plusone
\ifthirdargument
- \setuevalue{#command}{\groupedcommand{\expandafter\noexpand\begincsname\??alternativestyle#command\endcsname}{}}%
+ \setuevalue{#command}{\triggergroupedcommandcs\begincsname\??alternativestyle#command\endcsname}%
\else
- \setuvalue{#command}{\groupedcommand{#variantone}{}}%
+ \setuvalue{#command}{\triggergroupedcommand{#variantone}}%
\fi
\else
- \setuvalue{#command}{\groupedcommand{#variantone}{}}%
+ \setuvalue{#command}{\triggergroupedcommand{#variantone}}%
\fi\fi}
\def\font_helpers_apply_alternative_style
@@ -279,17 +279,26 @@
\fi\fi
\endcsname{#name}}
+% \setvalue{\??styleargument1}#name%
+% {\groupedcommand{\begincsname#name\endcsname}{}}
+
\setvalue{\??styleargument1}#name%
- {\groupedcommand{\csname#name\endcsname}{}}
+ {\expandafter\triggergroupedcommandcs\begincsname#name\endcsname}
+
+% \setvalue{\??styleargument2}#name%
+% {\groupedcommand{\font_styles_use_defined{#name}}{}} % or {\font_styles_apply_grouped{#name}}
\setvalue{\??styleargument2}#name%
- {\groupedcommand{\font_styles_use_defined{#name}}{}} % or {\font_styles_apply_grouped{#name}}
+ {\triggergroupedcommand{\font_styles_use_defined{#name}}} % or {\font_styles_apply_grouped{#name}}
\setvalue{\??styleargument3}#specification%
{\doifelseassignment{#specification}\font_styles_assignment\font_styles_direct{#specification}}
-\def\font_styles_assignment#specification{\groupedcommand{\font_styles_use_generic{#specification}}{}}
-\def\font_styles_direct #specification{\groupedcommand{\definedfont[#specification]}{}}
+% \def\font_styles_assignment#specification{\groupedcommand{\font_styles_use_generic{#specification}}{}}
+% \def\font_styles_direct #specification{\groupedcommand{\definedfont[#specification]}{}}
+
+\def\font_styles_assignment#specification{\triggergroupedcommand{\font_styles_use_generic{#specification}}}
+\def\font_styles_direct #specification{\triggergroupedcommand{\definedfont[#specification]}}
% environments
diff --git a/tex/context/base/mkiv/font-sym.mkvi b/tex/context/base/mkiv/font-sym.mkvi
index 0e709f161..3ff85fb4a 100644
--- a/tex/context/base/mkiv/font-sym.mkvi
+++ b/tex/context/base/mkiv/font-sym.mkvi
@@ -167,7 +167,7 @@
\def\font_basics_define_symbolic_font
{\definefont[currentsymbolfont][\askedsymbolfont]%
\currentsymbolfont
- \global\expandafter\let\csname\??symbolfont\askedsymbolfont\endcsname\lastrawfontcall}
+ \expandafter\glet\csname\??symbolfont\askedsymbolfont\endcsname\lastrawfontcall}
\unexpanded\def\getnamedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_fontchar{#character}}}
\unexpanded\def\getnamedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_fontchar{#character}}}
diff --git a/tex/context/base/mkiv/font-syn.lua b/tex/context/base/mkiv/font-syn.lua
index 52f425db3..dfe32b57b 100644
--- a/tex/context/base/mkiv/font-syn.lua
+++ b/tex/context/base/mkiv/font-syn.lua
@@ -1172,7 +1172,7 @@ local function analyzefiles(olddata)
report_names("scanning path %a for %s files",blobpath,suffix)
end, function(blobtype,blobpath,pattern,total,checked,done)
blobpath = resolveprefix(blobpath) -- no shortcut
- report_names("%s entries found, %s %s files checked, %s okay",total,checked,suffix,done)
+ report_names("%s %s files checked, %s okay",checked,suffix,done)
end)
end
@@ -2009,7 +2009,8 @@ local lastlookups, lastpattern = { }, ""
local function look_them_up(lookups,specification)
for key, value in sortedhash(specification) do
- local t, n = { }, 0
+ local t = { }
+ local n = 0
if find(value,"*",1,true) then
value = topattern(value)
for i=1,#lookups do
diff --git a/tex/context/base/mkiv/font-tfm.lua b/tex/context/base/mkiv/font-tfm.lua
index 0059e6296..6e4f86980 100644
--- a/tex/context/base/mkiv/font-tfm.lua
+++ b/tex/context/base/mkiv/font-tfm.lua
@@ -9,6 +9,7 @@ if not modules then modules = { } end modules ['font-tfm'] = {
local next, type = next, type
local match, format = string.match, string.format
local concat, sortedhash = table.concat, table.sortedhash
+local idiv = number.idiv
local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
local trace_features = false trackers.register("tfm.features", function(v) trace_features = v end)
@@ -21,6 +22,7 @@ local setmetatableindex = table.setmetatableindex
local fonts = fonts
local handlers = fonts.handlers
+local helpers = fonts.helpers
local readers = fonts.readers
local constructors = fonts.constructors
local encodings = fonts.encodings
@@ -39,6 +41,8 @@ local registertfmfeature = tfmfeatures.register
local tfmenhancers = constructors.enhancers.tfm
local registertfmenhancer = tfmenhancers.register
+local charcommand = helpers.commands.char
+
constructors.resolvevirtualtoo = false -- wil be set in font-ctx.lua
fonts.formats.tfm = "type1" -- we need to have at least a value here
@@ -114,219 +118,266 @@ local depth = { } -- table.setmetatableindex("number")
--
-- So "czechdqcheat=yes" is then a valid feature. And yes, it's a cheat.
+local read_from_tfm, check_tfm do
-local function read_from_tfm(specification)
- local filename = specification.filename
- local size = specification.size
- depth[filename] = (depth[filename] or 0) + 1
- if trace_defining then
- report_defining("loading tfm file %a at size %s",filename,size)
- end
- local tfmdata = font.read_tfm(filename,size) -- not cached, fast enough
- if tfmdata then
-
- local features = specification.features and specification.features.normal or { }
- local features = constructors.checkedfeatures("tfm",features)
- specification.features.normal = features
+ local tfmreaders = context and tfm.readers
+ local loadtfmvf = tfmreaders and tfmreaders.loadtfmvf
+ local loadtfm = font.read_tfm
+ local loadvf = font.read_vf
- -- If reencode returns a new table, we assume that we're doing something
- -- special. An 'auto' reencode pickt up its vector from the pfb file.
+ directives.register("fonts.tfm.builtin",function(v)
+ loadtfmvf = tfmreaders and tfmreaders.loadtfmvf
+ if v and loadtfm then
+ loadtfmvf = false
+ end
+ end)
- local newtfmdata = (depth[filename] == 1) and tfm.reencode(tfmdata,specification)
- if newtfmdata then
- tfmdata = newtfmdata
+ read_from_tfm = function(specification)
+ local filename = specification.filename
+ local size = specification.size
+ depth[filename] = (depth[filename] or 0) + 1
+ if trace_defining then
+ report_defining("loading tfm file %a at size %s",filename,size)
+ end
+ local tfmdata -- not cached, fast enough
+ if loadtfmvf then
+ tfmdata = loadtfmvf(filename,size)
+ else
+ tfmdata = loadtfm(filename,size)
end
+ if tfmdata then
- local resources = tfmdata.resources or { }
- local properties = tfmdata.properties or { }
- local parameters = tfmdata.parameters or { }
- local shared = tfmdata.shared or { }
- --
- shared.features = features
- shared.resources = resources
- --
- properties.name = tfmdata.name -- todo: fallback
- properties.fontname = tfmdata.fontname -- todo: fallback
- properties.psname = tfmdata.psname -- todo: fallback
- properties.fullname = tfmdata.fullname -- todo: fallback
- properties.filename = specification.filename -- todo: fallback
- properties.format = fonts.formats.tfm -- better than nothing
- --
- tfmdata.properties = properties
- tfmdata.resources = resources
- tfmdata.parameters = parameters
- tfmdata.shared = shared
- --
- shared.rawdata = { resources = resources }
- shared.features = features
- --
- -- The next branch is only entered when we have a proper encoded file i.e.
- -- unicodes and such. It really nakes no sense to do feature juggling when
- -- we have no names and unicodes.
- --
- if newtfmdata then
- --
- -- Some opentype processing assumes these to be present:
- --
- if not resources.marks then
- resources.marks = { }
- end
- if not resources.sequences then
- resources.sequences = { }
- end
- if not resources.features then
- resources.features = {
- gsub = { },
- gpos = { },
- }
- end
- if not tfmdata.changed then
- tfmdata.changed = { }
- end
- if not tfmdata.descriptions then
- tfmdata.descriptions = tfmdata.characters
+ local features = specification.features and specification.features.normal or { }
+ local features = constructors.checkedfeatures("tfm",features)
+ specification.features.normal = features
+
+ -- If reencode returns a new table, we assume that we're doing something
+ -- special. An 'auto' reencode picks up its vector from the pfb file.
+
+ local newtfmdata = (depth[filename] == 1) and tfm.reencode(tfmdata,specification)
+ if newtfmdata then
+ tfmdata = newtfmdata
end
+
+ local resources = tfmdata.resources or { }
+ local properties = tfmdata.properties or { }
+ local parameters = tfmdata.parameters or { }
+ local shared = tfmdata.shared or { }
--
- -- It might be handy to have this:
- --
- otf.readers.addunicodetable(tfmdata)
- --
- -- We make a pseudo opentype font, e.g. kerns and ligatures etc:
- --
- tfmenhancers.apply(tfmdata,filename)
- --
- -- Now user stuff can kick in.
- --
- constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm)
- --
- -- As that can also mess with names and such, we are now ready for finalizing
- -- the unicode information. This is a different order that for instance type one
- -- (afm) files. First we try to deduce unicodes from already present information.
+ shared.features = features
+ shared.resources = resources
--
- otf.readers.unifymissing(tfmdata)
+ properties.name = tfmdata.name -- todo: fallback
+ properties.fontname = tfmdata.fontname -- todo: fallback
+ properties.psname = tfmdata.psname -- todo: fallback
+ properties.fullname = tfmdata.fullname -- todo: fallback
+ properties.filename = specification.filename -- todo: fallback
+ properties.format = tfmdata.format or fonts.formats.tfm -- better than nothing
+ properties.usedbitmap = tfmdata.usedbitmap
--
- -- Next we fill in the gaps, based on names from teh agl. Probably not much will
- -- happen here.
+ tfmdata.properties = properties
+ tfmdata.resources = resources
+ tfmdata.parameters = parameters
+ tfmdata.shared = shared
--
- fonts.mappings.addtounicode(tfmdata,filename)
+ shared.rawdata = { resources = resources }
+ shared.features = features
--
- -- The tounicode data is passed to the backend that constructs the vectors for us.
+ -- The next branch is only entered when we have a proper encoded file i.e.
+ -- unicodes and such. It really nakes no sense to do feature juggling when
+ -- we have no names and unicodes.
--
- tfmdata.tounicode = 1
- local tounicode = fonts.mappings.tounicode
- for unicode, v in next, tfmdata.characters do
- local u = v.unicode
- if u then
- v.tounicode = tounicode(u)
+ if newtfmdata then
+ --
+ -- Some opentype processing assumes these to be present:
+ --
+ if not resources.marks then
+ resources.marks = { }
+ end
+ if not resources.sequences then
+ resources.sequences = { }
+ end
+ if not resources.features then
+ resources.features = {
+ gsub = { },
+ gpos = { },
+ }
+ end
+ if not tfmdata.changed then
+ tfmdata.changed = { }
+ end
+ if not tfmdata.descriptions then
+ tfmdata.descriptions = tfmdata.characters
+ end
+ --
+ -- It might be handy to have this:
+ --
+ otf.readers.addunicodetable(tfmdata)
+ --
+ -- We make a pseudo opentype font, e.g. kerns and ligatures etc:
+ --
+ tfmenhancers.apply(tfmdata,filename)
+ --
+ -- Now user stuff can kick in.
+ --
+ constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm)
+ --
+ -- As that can also mess with names and such, we are now ready for finalizing
+ -- the unicode information. This is a different order that for instance type one
+ -- (afm) files. First we try to deduce unicodes from already present information.
+ --
+ otf.readers.unifymissing(tfmdata)
+ --
+ -- Next we fill in the gaps, based on names from teh agl. Probably not much will
+ -- happen here.
+ --
+ fonts.mappings.addtounicode(tfmdata,filename)
+ --
+ -- The tounicode data is passed to the backend that constructs the vectors for us.
+ --
+ tfmdata.tounicode = 1
+ local tounicode = fonts.mappings.tounicode
+ for unicode, v in next, tfmdata.characters do
+ local u = v.unicode
+ if u then
+ v.tounicode = tounicode(u)
+ end
+ end
+ --
+ -- However, when we use a bitmap font those vectors can't be constructed because
+ -- that information is not carried with those fonts (there is no name info, nor
+ -- proper index info, nor unicodes at that end). So, we provide it ourselves.
+ --
+ if tfmdata.usedbitmap then
+ tfm.addtounicode(tfmdata)
end
end
--
- -- However, when we use a bitmap font those vectors can't be constructed because
- -- that information is not carried with those fonts (there is no name info, nor
- -- proper index info, nor unicodes at that end). So, we provide it ourselves.
+ shared.processes = next(features) and tfm.setfeatures(tfmdata,features) or nil
--
- if tfmdata.usedbitmap then
- tfm.addtounicode(tfmdata)
+ if size < 0 then
+ size = idiv(65536 * -size,100)
end
- end
- --
- shared.processes = next(features) and tfm.setfeatures(tfmdata,features) or nil
- --
- parameters.factor = 1 -- already scaled
- parameters.size = size
- parameters.slant = parameters.slant or parameters[1] or 0
- parameters.space = parameters.space or parameters[2] or 0
- parameters.space_stretch = parameters.space_stretch or parameters[3] or 0
- parameters.space_shrink = parameters.space_shrink or parameters[4] or 0
- parameters.x_height = parameters.x_height or parameters[5] or 0
- parameters.quad = parameters.quad or parameters[6] or 0
- parameters.extra_space = parameters.extra_space or parameters[7] or 0
- --
- constructors.enhanceparameters(parameters) -- official copies for us
- --
- properties.private = properties.private or tfmdata.private or privateoffset
- --
- if newtfmdata then
+ parameters.factor = 1 -- already scaled
+ parameters.units = 1000 -- just in case
+ parameters.size = size
+ parameters.slant = parameters.slant or parameters[1] or 0
+ parameters.space = parameters.space or parameters[2] or 0
+ parameters.space_stretch = parameters.space_stretch or parameters[3] or 0
+ parameters.space_shrink = parameters.space_shrink or parameters[4] or 0
+ parameters.x_height = parameters.x_height or parameters[5] or 0
+ parameters.quad = parameters.quad or parameters[6] or 0
+ parameters.extra_space = parameters.extra_space or parameters[7] or 0
--
- -- We do nothing as we assume flat tfm files. It would become real messy
- -- otherwise and I don't have something for testing on my system anyway.
+ constructors.enhanceparameters(parameters) -- official copies for us
--
- elseif constructors.resolvevirtualtoo then
- 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
- if vfdata then
- local chars = tfmdata.characters
- for k,v in next, vfdata.characters do
- chars[k].commands = v.commands
+ properties.private = properties.private or tfmdata.private or privateoffset
+ --
+ if newtfmdata then
+ --
+ -- We do nothing as we assume flat tfm files. It would become real messy
+ -- otherwise and I don't have something for testing on my system anyway.
+ --
+ elseif loadtfmvf then
+ -- already loaded
+ local fonts = tfmdata.fonts
+ if fonts then
+ for i=1,#fonts do
+ local font = fonts[i]
+ local id = font.id
+ if not id then
+ local name = font.name
+ local size = font.size
+ if name and size then
+ local data, id = constructors.readanddefine(name,size)
+ if id then
+ font.id = id
+ font.name = nil
+ font.size = nil
+ end
+ end
+ end
end
- properties.virtualized = true
- tfmdata.fonts = vfdata.fonts
- tfmdata.type = "virtual" -- else nested calls with cummulative scaling
- local fontlist = vfdata.fonts
- local name = file.nameonly(filename)
- for i=1,#fontlist do
- local n = fontlist[i].name
- local s = fontlist[i].size
- local d = depth[filename]
- s = constructors.scaled(s,vfdata.designsize)
- if d > tfm.maxnestingdepth then
- report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth)
- fontlist[i] = { id = 0 }
- elseif (d > 1) and (s > tfm.maxnestingsize) then
- report_defining("virtual font %a exceeds size %s",n,s)
- fontlist[i] = { id = 0 }
- else
- local t, id = fonts.constructors.readanddefine(n,s)
- fontlist[i] = { id = id }
+ end
+ elseif constructors.resolvevirtualtoo then
+ fonts.loggers.register(tfmdata,file.suffix(filename),specification) -- strange, why here
+ local vfname = findbinfile(specification.name, 'ovf')
+ if vfname and vfname ~= "" then
+ local vfdata = loadvf(vfname,size)
+ if vfdata then
+ local chars = tfmdata.characters
+ for k,v in next, vfdata.characters do
+ chars[k].commands = v.commands
+ end
+ properties.virtualized = true
+ tfmdata.fonts = vfdata.fonts
+ tfmdata.type = "virtual" -- else nested calls with cummulative scaling
+ local fontlist = vfdata.fonts
+ local name = file.nameonly(filename)
+ for i=1,#fontlist do
+ local n = fontlist[i].name
+ local s = fontlist[i].size
+ local d = depth[filename]
+ s = constructors.scaled(s,vfdata.designsize)
+ if d > tfm.maxnestingdepth then
+ report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth)
+ fontlist[i] = { id = 0 }
+ elseif (d > 1) and (s > tfm.maxnestingsize) then
+ report_defining("virtual font %a exceeds size %s",n,s)
+ fontlist[i] = { id = 0 }
+ else
+ local t, id = constructors.readanddefine(n,s)
+ fontlist[i] = { id = id }
+ end
end
end
end
end
+ --
+ -- This is for old times sake (and context specific) so we comment it. It has
+ -- to do with encoding prefixes (a context naming that was later adopted by
+ -- the lm/gyre project)
+ --
+ -- if not features.encoding then
+ -- local encoding, filename = match(properties.filename,"^(.-)%-(.*)$")
+ -- if filename and encoding and encodings.known and encodings.known[encoding] then
+ -- features.encoding = encoding
+ -- end
+ -- end
+ --
+ -- Some afterthoughts:
+ --
+ properties.haskerns = true
+ properties.hasligatures = true
+ properties.hasitalics = true
+ resources.unicodes = { }
+ resources.lookuptags = { }
+ --
+ depth[filename] = depth[filename] - 1
+ --
+ return tfmdata
+ else
+ depth[filename] = depth[filename] - 1
end
- --
- -- This is for old times sake (and context specific) so we comment it. It has
- -- to do with encoding prefixes (a context naming that was later adopted by
- -- the lm/gyre project)
- --
- -- if not features.encoding then
- -- local encoding, filename = match(properties.filename,"^(.-)%-(.*)$")
- -- if filename and encoding and encodings.known and encodings.known[encoding] then
- -- features.encoding = encoding
- -- end
- -- end
- --
- -- Some afterthoughts:
- --
- properties.haskerns = true
- properties.hasligatures = true
- resources.unicodes = { }
- resources.lookuptags = { }
- --
- depth[filename] = depth[filename] - 1
- --
- return tfmdata
- else
- depth[filename] = depth[filename] - 1
end
-end
-local function check_tfm(specification,fullname) -- we could split up like afm/otf
- local foundname = findbinfile(fullname, 'tfm') or ""
- if foundname == "" then
- foundname = findbinfile(fullname, 'ofm') or "" -- not needed in context
- end
- if foundname == "" then
- foundname = fonts.names.getfilename(fullname,"tfm") or ""
- end
- if foundname ~= "" then
- specification.filename = foundname
- specification.format = "ofm"
- return read_from_tfm(specification)
- elseif trace_defining then
- report_defining("loading tfm with name %a fails",specification.name)
+ check_tfm = function(specification,fullname) -- we could split up like afm/otf
+ local foundname = findbinfile(fullname, 'tfm') or ""
+ if foundname == "" then
+ foundname = findbinfile(fullname, 'ofm') or "" -- not needed in context
+ end
+ if foundname == "" then
+ foundname = fonts.names.getfilename(fullname,"tfm") or ""
+ end
+ if foundname ~= "" then
+ specification.filename = foundname
+ specification.format = "ofm"
+ return read_from_tfm(specification)
+ elseif trace_defining then
+ report_defining("loading tfm with name %a fails",specification.name)
+ end
end
+
end
readers.check_tfm = check_tfm
@@ -409,7 +460,7 @@ do
local vector = false
if type(pfbfile) == "string" then
- local pfb = fonts.constructors.handlers.pfb
+ local pfb = constructors.handlers.pfb
if pfb and pfb.loadvector then
local v, e = pfb.loadvector(pfbfile)
if v then
@@ -438,7 +489,7 @@ do
local originals = tfmdata.characters
local indices = { }
local parentfont = { "font", 1 }
- local private = tfmdata or fonts.constructors.privateoffset
+ local private = tfmdata.privateoffset or constructors.privateoffset
local reported = encdone[tfmfile][encfile]
-- create characters table
@@ -463,9 +514,9 @@ do
indices[index] = unicode
original.name = name -- so one can lookup weird names
if backmap then
- original.index = backmap[name]
+ original.index = backmap[name]
else -- probably bitmap
- original.commands = { parentfont, { "char", index } }
+ original.commands = { parentfont, charcommand[index] } -- or "slot"
original.oindex = index
end
done[name] = true
@@ -512,6 +563,7 @@ do
tfmdata.psname = file.nameonly(pfbfile or tfmdata.name)
tfmdata.filename = pfbfile
tfmdata.encodingbytes = 2
+ -- tfmdata.format = bitmap and "type3" or "type1"
tfmdata.format = "type1"
tfmdata.tounicode = 1
tfmdata.embedding = "subset"
@@ -548,24 +600,18 @@ end
end
]]
- local flushstreamobject = lpdf and lpdf.flushstreamobject
- local setfontattributes = pdf.setfontattributes
+ local flushstreamobject = lpdf and lpdf.flushstreamobject -- context
+ local setfontattributes = lpdf and lpdf.setfontattributes -- context
- if flushstreamobject then
- -- we're in context
- else
+ if not flushstreamobject then
flushstreamobject = function(data)
- return pdf.obj {
- immediate = true,
- type = "stream",
- string = data,
- }
+ return pdf.obj { immediate = true, type = "stream", string = data } -- generic
end
end
if not setfontattributes then
setfontattributes = function(id,data)
- print(format("your luatex is too old so no tounicode bitmap font%i",id))
+ return pdf.setfontattributes(id,data) -- generic
end
end
@@ -593,7 +639,7 @@ end
-- Now we implement the regular features handlers. We need to convert the
-- tfm specific structures to opentype structures. In basemode they are
--- converted back so that is a bti of a waste but it's fast enough.
+-- converted back so that is a bit of a waste but it's fast enough.
do
diff --git a/tex/context/base/mkiv/font-tra.mkiv b/tex/context/base/mkiv/font-tra.mkiv
index c51ba78fc..205ca5ca0 100644
--- a/tex/context/base/mkiv/font-tra.mkiv
+++ b/tex/context/base/mkiv/font-tra.mkiv
@@ -188,7 +188,7 @@
% \showotfstepmessages\recurselevel
% \blank
% \startlinecorrection
-% \dontleavehmode\bgroup\resetallattributes\pardir TLT\textdir TLT\relax\tttf\recurselevel: \showotfstepchars\recurselevel\egroup
+% \dontleavehmode\bgroup\resetallattributes\lefttoright\tttf\recurselevel: \showotfstepchars\recurselevel\egroup
% \stoplinecorrection
% \blank
% \startlinecorrection
diff --git a/tex/context/base/mkiv/font-ttf.lua b/tex/context/base/mkiv/font-ttf.lua
index df08787f9..d2fe0917c 100644
--- a/tex/context/base/mkiv/font-ttf.lua
+++ b/tex/context/base/mkiv/font-ttf.lua
@@ -35,26 +35,53 @@ if not modules then modules = { } end modules ['font-ttf'] = {
local next, type, unpack = next, type, unpack
local band, rshift = bit32.band, bit32.rshift
local sqrt, round = math.sqrt, math.round
-local char = string.char
+local char, rep = string.char, string.rep
local concat = table.concat
+local idiv = number.idiv
+local setmetatableindex = table.setmetatableindex
-local report = logs.reporter("otf reader","ttf")
+local report = logs.reporter("otf reader","ttf")
-local trace_deltas = false
+local trace_deltas = false
-local readers = fonts.handlers.otf.readers
-local streamreader = readers.streamreader
+local readers = fonts.handlers.otf.readers
+local streamreader = readers.streamreader
-local setposition = streamreader.setposition
-local getposition = streamreader.getposition
-local skipbytes = streamreader.skip
-local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer
-local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
-local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer
-local readchar = streamreader.readinteger1 -- 8-bit signed integer
-local readshort = streamreader.readinteger2 -- 16-bit signed integer
-local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed number with the low 14 bits of fraction (2.14) (F2DOT14)
-local readinteger = streamreader.readinteger1
+local setposition = streamreader.setposition
+local getposition = streamreader.getposition
+local skipbytes = streamreader.skip
+local readbyte = streamreader.readcardinal1 -- 8-bit unsigned integer
+local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
+local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer
+local readchar = streamreader.readinteger1 -- 8-bit signed integer
+local readshort = streamreader.readinteger2 -- 16-bit signed integer
+local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed number with the low 14 bits of fraction (2.14) (F2DOT14)
+local readinteger = streamreader.readinteger1
+local readcardinaltable = streamreader.readcardinaltable
+local readintegertable = streamreader.readintegertable
+
+directives.register("fonts.streamreader",function()
+
+ streamreader = utilities.streams
+
+ setposition = streamreader.setposition
+ getposition = streamreader.getposition
+ skipbytes = streamreader.skip
+ readbyte = streamreader.readcardinal1
+ readushort = streamreader.readcardinal2
+ readulong = streamreader.readcardinal4
+ readchar = streamreader.readinteger1
+ readshort = streamreader.readinteger2
+ read2dot14 = streamreader.read2dot14
+ readinteger = streamreader.readinteger1
+ readcardinaltable = streamreader.readcardinaltable
+ readintegertable = streamreader.readintegertable
+
+end)
+
+local short = 2
+local ushort = 2
+local ulong = 4
local helpers = readers.helpers
local gotodatatable = helpers.gotodatatable
@@ -90,22 +117,41 @@ local function mergecomposites(glyphs,shapes)
local yscale = matrix[4]
local xoffset = matrix[5]
local yoffset = matrix[6]
- for i=1,#subpoints do
- local p = subpoints[i]
- local x = p[1]
- local y = p[2]
- nofpoints = nofpoints + 1
- points[nofpoints] = {
- xscale * x + xrotate * y + xoffset,
- yscale * y + yrotate * x + yoffset,
- p[3]
- }
+ local count = #subpoints
+ if xscale == 1 and yscale == 1 and xrotate == 0 and yrotate == 0 then
+ for i=1,count do
+ local p = subpoints[i]
+ nofpoints = nofpoints + 1
+ points[nofpoints] = {
+ p[1] + xoffset,
+ p[2] + yoffset,
+ p[3]
+ }
+ end
+ else
+ for i=1,count do
+ local p = subpoints[i]
+ local x = p[1]
+ local y = p[2]
+ nofpoints = nofpoints + 1
+ points[nofpoints] = {
+ xscale * x + xrotate * y + xoffset,
+ yscale * y + yrotate * x + yoffset,
+ p[3]
+ }
+ end
end
- for i=1,#subcontours do
+ local subcount = #subcontours
+ if subcount == 1 then
nofcontours = nofcontours + 1
- contours[nofcontours] = offset + subcontours[i]
+ contours[nofcontours] = offset + subcontours[1]
+ else
+ for i=1,#subcontours do
+ nofcontours = nofcontours + 1
+ contours[nofcontours] = offset + subcontours[i]
+ end
end
- offset = offset + #subpoints
+ offset = offset + count
else
report("missing contours composite %s, component %s of %s, glyph %s",index,i,#components,subindex)
end
@@ -116,7 +162,8 @@ local function mergecomposites(glyphs,shapes)
return contours, points
end
- for index=1,#glyphs do
+-- for index=1,#glyphs do
+ for index=0,#glyphs-1 do
local shape = shapes[index]
if shape then
local components = shape.components
@@ -128,7 +175,7 @@ local function mergecomposites(glyphs,shapes)
end
-local function readnothing(f,nofcontours)
+local function readnothing(f)
return {
type = "nothing",
}
@@ -259,7 +306,8 @@ end
local quadratic = false
local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox overhead
- for index=1,#glyphs do
+-- for index=1,#glyphs do
+ for index=0,#glyphs-1 do
local shape = shapes[index]
if shape then
local glyph = glyphs[index]
@@ -271,7 +319,8 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox
local nofsegments = 0
glyph.segments = segments
if nofcontours > 0 then
- local px, py = 0, 0 -- we could use these in calculations which saves a copy
+ local px = 0
+ local py = 0
local first = 1
for i=1,nofcontours do
local last = contours[i]
@@ -299,15 +348,20 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox
end
control_pt = first_pt
end
- local x, y = first_pt[1], first_pt[2]
+ local x = first_pt[1]
+ local y = first_pt[2]
if not done then
- xmin, ymin, xmax, ymax = x, y, x, y
+ xmin = x
+ ymin = y
+ xmax = x
+ ymax = y
done = true
end
nofsegments = nofsegments + 1
segments[nofsegments] = { x, y, "m" } -- "moveto"
if not quadratic then
- px, py = x, y
+ px = x
+ py = y
end
local previous_pt = first_pt
for i=first,last do
@@ -327,8 +381,10 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox
control_pt = current_pt
end
elseif current_on then
- local x1, y1 = control_pt[1], control_pt[2]
- local x2, y2 = current_pt[1], current_pt[2]
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
+ local x2 = current_pt[1]
+ local y2 = current_pt[2]
nofsegments = nofsegments + 1
if quadratic then
segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto"
@@ -338,8 +394,10 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox
end
control_pt = false
else
- local x2, y2 = (previous_pt[1]+current_pt[1])/2, (previous_pt[2]+current_pt[2])/2
- local x1, y1 = control_pt[1], control_pt[2]
+ local x2 = (previous_pt[1]+current_pt[1])/2
+ local y2 = (previous_pt[2]+current_pt[2])/2
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
nofsegments = nofsegments + 1
if quadratic then
segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto"
@@ -355,14 +413,17 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox
-- we're already done, probably a simple curve
else
nofsegments = nofsegments + 1
- local x2, y2 = first_pt[1], first_pt[2]
+ local x2 = first_pt[1]
+ local y2 = first_pt[2]
if not control_pt then
segments[nofsegments] = { x2, y2, "l" } -- "lineto"
elseif quadratic then
- local x1, y1 = control_pt[1], control_pt[2]
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
segments[nofsegments] = { x1, y1, x2, y2, "q" } -- "quadraticto"
else
- local x1, y1 = control_pt[1], control_pt[2]
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
x1, y1, x2, y2, px, py = curveto(x1, y1, px, py, x2, y2)
segments[nofsegments] = { x1, y1, x2, y2, px, py, "c" } -- "curveto"
-- px, py = x2, y2
@@ -379,7 +440,8 @@ local function contours2outlines_normal(glyphs,shapes) -- maybe accept the bbox
end
local function contours2outlines_shaped(glyphs,shapes,keepcurve)
- for index=1,#glyphs do
+-- for index=1,#glyphs do
+ for index=0,#glyphs-1 do
local shape = shapes[index]
if shape then
local glyph = glyphs[index]
@@ -425,7 +487,8 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
end
control_pt = first_pt
end
- local x, y = first_pt[1], first_pt[2]
+ local x = first_pt[1]
+ local y = first_pt[2]
if not done then
xmin, ymin, xmax, ymax = x, y, x, y
done = true
@@ -438,7 +501,8 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
segments[nofsegments] = { x, y, "m" } -- "moveto"
end
if not quadratic then
- px, py = x, y
+ px = x
+ py = y
end
local previous_pt = first_pt
for i=first,last do
@@ -448,7 +512,8 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
if previous_on then
if current_on then
-- both normal points
- local x, y = current_pt[1], current_pt[2]
+ local x = current_pt[1]
+ local y = current_pt[2]
if x < xmin then xmin = x elseif x > xmax then xmax = x end
if y < ymin then ymin = y elseif y > ymax then ymax = y end
if keepcurve then
@@ -456,14 +521,17 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
segments[nofsegments] = { x, y, "l" } -- "lineto"
end
if not quadratic then
- px, py = x, y
+ px = x
+ py = y
end
else
control_pt = current_pt
end
elseif current_on then
- local x1, y1 = control_pt[1], control_pt[2]
- local x2, y2 = current_pt[1], current_pt[2]
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
+ local x2 = current_pt[1]
+ local y2 = current_pt[2]
if quadratic then
if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end
if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end
@@ -486,8 +554,10 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
end
control_pt = false
else
- local x2, y2 = (previous_pt[1]+current_pt[1])/2, (previous_pt[2]+current_pt[2])/2
- local x1, y1 = control_pt[1], control_pt[2]
+ local x2 = (previous_pt[1]+current_pt[1])/2
+ local y2 = (previous_pt[2]+current_pt[2])/2
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
if quadratic then
if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end
if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end
@@ -520,8 +590,10 @@ local function contours2outlines_shaped(glyphs,shapes,keepcurve)
segments[nofsegments] = { first_pt[1], first_pt[2], "l" } -- "lineto"
end
else
- local x1, y1 = control_pt[1], control_pt[2]
- local x2, y2 = first_pt[1], first_pt[2]
+ local x1 = control_pt[1]
+ local y1 = control_pt[2]
+ local x2 = first_pt[1]
+ local y2 = first_pt[2]
if x1 < xmin then xmin = x1 elseif x1 > xmax then xmax = x1 end
if y1 < ymin then ymin = y1 elseif y1 > ymax then ymax = y1 end
if quadratic then
@@ -558,8 +630,13 @@ end
local c_zero = char(0)
local s_zero = char(0,0)
+-- local shorthash = setmetatableindex(function(t,k)
+-- t[k] = char(band(rshift(k,8),0xFF),band(k,0xFF)) return t[k]
+-- end)
+
local function toushort(n)
return char(band(rshift(n,8),0xFF),band(n,0xFF))
+ -- return shorthash[n]
end
local function toshort(n)
@@ -567,125 +644,152 @@ local function toshort(n)
n = n + 0x10000
end
return char(band(rshift(n,8),0xFF),band(n,0xFF))
+ -- return shorthash[n]
end
-- todo: we can reuse result, xpoints and ypoints
+local chars = setmetatableindex(function(t,k)
+ for i=0,255 do local v = char(i) t[i] = v end return t[k]
+end)
+
local function repackpoints(glyphs,shapes)
local noboundingbox = { 0, 0, 0, 0 }
local result = { } -- reused
- for index=1,#glyphs do
+ local xpoints = { } -- reused
+ local ypoints = { } -- reused
+ for index=0,#glyphs-1 do
local shape = shapes[index]
if shape then
local r = 0
local glyph = glyphs[index]
- if false then -- shape.type == "composite"
- -- we merged them
- else
- local contours = shape.contours
- local nofcontours = contours and #contours or 0
- local boundingbox = glyph.boundingbox or noboundingbox
- r = r + 1 result[r] = toshort(nofcontours)
- r = r + 1 result[r] = toshort(boundingbox[1]) -- xmin
- r = r + 1 result[r] = toshort(boundingbox[2]) -- ymin
- r = r + 1 result[r] = toshort(boundingbox[3]) -- xmax
- r = r + 1 result[r] = toshort(boundingbox[4]) -- ymax
- if nofcontours > 0 then
- for i=1,nofcontours do
- r = r + 1 result[r] = toshort(contours[i]-1)
- end
- r = r + 1 result[r] = s_zero -- no instructions
- local points = shape.points
- local currentx = 0
- local currenty = 0
- local xpoints = { }
- local ypoints = { }
- local x = 0
- local y = 0
- local lastflag = nil
- local nofflags = 0
- for i=1,#points do
- local pt = points[i]
- local px = pt[1]
- local py = pt[2]
- local fl = pt[3] and 0x01 or 0x00
- if px == currentx then
- fl = fl + 0x10
+ local contours = shape.contours
+ local nofcontours = contours and #contours or 0
+ local boundingbox = glyph.boundingbox or noboundingbox
+ r = r + 1 result[r] = toshort(nofcontours)
+ r = r + 1 result[r] = toshort(boundingbox[1]) -- xmin
+ r = r + 1 result[r] = toshort(boundingbox[2]) -- ymin
+ r = r + 1 result[r] = toshort(boundingbox[3]) -- xmax
+ r = r + 1 result[r] = toshort(boundingbox[4]) -- ymax
+ if nofcontours > 0 then
+ for i=1,nofcontours do
+ r = r + 1 result[r] = toshort(contours[i]-1)
+ end
+ r = r + 1 result[r] = s_zero -- no instructions
+ local points = shape.points
+ local currentx = 0
+ local currenty = 0
+ -- local xpoints = { }
+ -- local ypoints = { }
+ local x = 0
+ local y = 0
+ local lastflag = nil
+ local nofflags = 0
+ for i=1,#points do
+ local pt = points[i]
+ local px = pt[1]
+ local py = pt[2]
+ local fl = pt[3] and 0x01 or 0x00
+ if px == currentx then
+ fl = fl + 0x10
+ else
+ local dx = round(px - currentx)
+ x = x + 1
+ if dx < -255 or dx > 255 then
+ xpoints[x] = toshort(dx)
+ elseif dx < 0 then
+ fl = fl + 0x02
+ -- xpoints[x] = char(-dx)
+ xpoints[x] = chars[-dx]
+ elseif dx > 0 then
+ fl = fl + 0x12
+ -- xpoints[x] = char(dx)
+ xpoints[x] = chars[dx]
else
- local dx = round(px - currentx)
- if dx < -255 or dx > 255 then
- x = x + 1 xpoints[x] = toshort(dx)
- elseif dx < 0 then
- fl = fl + 0x02
- x = x + 1 xpoints[x] = char(-dx)
- elseif dx > 0 then
- fl = fl + 0x12
- x = x + 1 xpoints[x] = char(dx)
- else
- fl = fl + 0x02
- x = x + 1 xpoints[x] = c_zero
- end
+ fl = fl + 0x02
+ xpoints[x] = c_zero
end
- if py == currenty then
- fl = fl + 0x20
+ end
+ if py == currenty then
+ fl = fl + 0x20
+ else
+ local dy = round(py - currenty)
+ y = y + 1
+ if dy < -255 or dy > 255 then
+ ypoints[y] = toshort(dy)
+ elseif dy < 0 then
+ fl = fl + 0x04
+ -- ypoints[y] = char(-dy)
+ ypoints[y] = chars[-dy]
+ elseif dy > 0 then
+ fl = fl + 0x24
+ -- ypoints[y] = char(dy)
+ ypoints[y] = chars[dy]
else
- local dy = round(py - currenty)
- if dy < -255 or dy > 255 then
- y = y + 1 ypoints[y] = toshort(dy)
- elseif dy < 0 then
- fl = fl + 0x04
- y = y + 1 ypoints[y] = char(-dy)
- elseif dy > 0 then
- fl = fl + 0x24
- y = y + 1 ypoints[y] = char(dy)
- else
- fl = fl + 0x04
- y = y + 1 ypoints[y] = c_zero
- end
- end
- currentx = px
- currenty = py
- if lastflag == fl then
- nofflags = nofflags + 1
- else -- if > 255
- if nofflags == 1 then
- r = r + 1 result[r] = char(lastflag)
- elseif nofflags == 2 then
- r = r + 1 result[r] = char(lastflag,lastflag)
- elseif nofflags > 2 then
- lastflag = lastflag + 0x08
- r = r + 1 result[r] = char(lastflag,nofflags-1)
- end
- nofflags = 1
- lastflag = fl
+ fl = fl + 0x04
+ ypoints[y] = c_zero
end
end
- if nofflags == 1 then
- r = r + 1 result[r] = char(lastflag)
- elseif nofflags == 2 then
- r = r + 1 result[r] = char(lastflag,lastflag)
- elseif nofflags > 2 then
- lastflag = lastflag + 0x08
- r = r + 1 result[r] = char(lastflag,nofflags-1)
+ currentx = px
+ currenty = py
+ if lastflag == fl then
+ nofflags = nofflags + 1
+ else -- if > 255
+ if nofflags == 1 then
+ -- r = r + 1 result[r] = char(lastflag)
+ r = r + 1 result[r] = chars[lastflag]
+ elseif nofflags == 2 then
+ r = r + 1 result[r] = char(lastflag,lastflag)
+ elseif nofflags > 2 then
+ lastflag = lastflag + 0x08
+ r = r + 1 result[r] = char(lastflag,nofflags-1)
+ end
+ nofflags = 1
+ lastflag = fl
end
- r = r + 1 result[r] = concat(xpoints)
- r = r + 1 result[r] = concat(ypoints)
end
+ if nofflags == 1 then
+ -- r = r + 1 result[r] = char(lastflag)
+ r = r + 1 result[r] = chars[lastflag]
+ elseif nofflags == 2 then
+ r = r + 1 result[r] = char(lastflag,lastflag)
+ elseif nofflags > 2 then
+ lastflag = lastflag + 0x08
+ r = r + 1 result[r] = char(lastflag,nofflags-1)
+ end
+ -- r = r + 1 result[r] = concat(xpoints)
+ -- r = r + 1 result[r] = concat(ypoints)
+ r = r + 1 result[r] = concat(xpoints,"",1,x)
+ r = r + 1 result[r] = concat(ypoints,"",1,y)
end
- glyph.stream = concat(result,"",1,r)
- else
- -- fatal
+ -- can be helper or delegated to user
+ local stream = concat(result,"",1,r)
+ local length = #stream
+ local padding = idiv(length+3,4) * 4 - length
+ if padding > 0 then
+ -- stream = stream .. rep("\0",padding) -- can be a repeater
+ if padding == 1 then
+ padding = "\0"
+ elseif padding == 2 then
+ padding = "\0\0"
+ else
+ padding = "\0\0\0"
+ end
+ padding = stream .. padding
+ end
+ glyph.stream = stream
end
end
end
-- end of converter
+local flags = { }
+
local function readglyph(f,nofcontours) -- read deltas here, saves space
- local points = { }
- local contours = { }
- local instructions = { }
- local flags = { }
+ local points = { }
+ -- local instructions = { }
+ local contours = { } -- readintegertable(f,nofcontours,short)
for i=1,nofcontours do
contours[i] = readshort(f) + 1
end
@@ -699,9 +803,15 @@ local function readglyph(f,nofcontours) -- read deltas here, saves space
local flag = readbyte(f)
flags[i] = flag
if band(flag,0x08) ~= 0 then
- for j=1,readbyte(f) do
+ local n = readbyte(f)
+ if n == 1 then
i = i + 1
flags[i] = flag
+ else
+ for j=1,n do
+ i = i + 1
+ flags[i] = flag
+ end
end
end
i = i + 1
@@ -710,16 +820,16 @@ local function readglyph(f,nofcontours) -- read deltas here, saves space
-- can be repeated
local x = 0
for i=1,nofpoints do
- local flag = flags[i]
- local short = band(flag,0x02) ~= 0
- local same = band(flag,0x10) ~= 0
- if short then
- if same then
+ local flag = flags[i]
+ -- local short = band(flag,0x04) ~= 0
+ -- local same = band(flag,0x20) ~= 0
+ if band(flag,0x02) ~= 0 then
+ if band(flag,0x10) ~= 0 then
x = x + readbyte(f)
else
x = x - readbyte(f)
end
- elseif same then
+ elseif band(flag,0x10) ~= 0 then
-- copy
else
x = x + readshort(f)
@@ -728,16 +838,16 @@ local function readglyph(f,nofcontours) -- read deltas here, saves space
end
local y = 0
for i=1,nofpoints do
- local flag = flags[i]
- local short = band(flag,0x04) ~= 0
- local same = band(flag,0x20) ~= 0
- if short then
- if same then
+ local flag = flags[i]
+ -- local short = band(flag,0x04) ~= 0
+ -- local same = band(flag,0x20) ~= 0
+ if band(flag,0x04) ~= 0 then
+ if band(flag,0x20) ~= 0 then
y = y + readbyte(f)
else
y = y - readbyte(f)
end
- elseif same then
+ elseif band(flag,0x20) ~= 0 then
-- copy
else
y = y + readshort(f)
@@ -833,7 +943,7 @@ local function readcomposite(f)
if band(flags,0x0100) ~= 0 then
instructions = true
end
- if not band(flags,0x0020) ~= 0 then -- f_more
+ if band(flags,0x0020) == 0 then -- f_more
break
end
end
@@ -858,21 +968,27 @@ function readers.loca(f,fontdata,specification)
-- locations are relative to the glypdata table (glyf)
local offset = fontdata.tables.glyf.offset
local format = fontdata.fontheader.indextolocformat
+ local profile = fontdata.maximumprofile
+ local nofglyphs = profile and profile.nofglyphs
local locations = { }
setposition(f,datatable.offset)
if format == 1 then
- local nofglyphs = datatable.length/4 - 2
+ if not nofglyphs then
+ nofglyphs = idiv(datatable.length,4) - 1
+ end
for i=0,nofglyphs do
locations[i] = offset + readulong(f)
end
fontdata.nofglyphs = nofglyphs
else
- local nofglyphs = datatable.length/2 - 2
+ if not nofglyphs then
+ nofglyphs = idiv(datatable.length,2) - 1
+ end
for i=0,nofglyphs do
locations[i] = offset + readushort(f) * 2
end
- fontdata.nofglyphs = nofglyphs
end
+ fontdata.nofglyphs = nofglyphs
fontdata.locations = locations
end
end
@@ -888,15 +1004,16 @@ function readers.glyf(f,fontdata,specification) -- part goes to cff module
local filesize = fontdata.filesize
local nothing = { 0, 0, 0, 0 }
local shapes = { }
- local loadshapes = specification.shapes or specification.instance
- for index=0,nofglyphs do
+ local loadshapes = specification.shapes or specification.instance or specification.streams
+ for index=0,nofglyphs-1 do
local location = locations[index]
+ local length = locations[index+1] - location
if location >= filesize then
report("discarding %s glyphs due to glyph location bug",nofglyphs-index+1)
fontdata.nofglyphs = index - 1
fontdata.badfont = true
break
- elseif location > 0 then
+ elseif length > 0 then
setposition(f,location)
local nofcontours = readshort(f)
glyphs[index].boundingbox = {
@@ -908,7 +1025,7 @@ function readers.glyf(f,fontdata,specification) -- part goes to cff module
if not loadshapes then
-- save space
elseif nofcontours == 0 then
- shapes[index] = readnothing(f,nofcontours)
+ shapes[index] = readnothing(f)
elseif nofcontours > 0 then
shapes[index] = readglyph(f,nofcontours)
else
@@ -916,7 +1033,7 @@ function readers.glyf(f,fontdata,specification) -- part goes to cff module
end
else
if loadshapes then
- shapes[index] = { }
+ shapes[index] = readnothing(f)
end
glyphs[index].boundingbox = nothing
end
@@ -933,7 +1050,13 @@ function readers.glyf(f,fontdata,specification) -- part goes to cff module
contours2outlines_shaped(glyphs,shapes,specification.shapes)
end
elseif specification.shapes then
- contours2outlines_normal(glyphs,shapes)
+ if specification.streams then
+ repackpoints(glyphs,shapes)
+ else
+ contours2outlines_normal(glyphs,shapes)
+ end
+ elseif specification.streams then
+ repackpoints(glyphs,shapes)
end
end
end
@@ -1234,10 +1357,6 @@ function readers.gvar(f,fontdata,specification,glyphdata,shapedata)
end
end
if shape.type == "glyph" then
--- if glyph.name == "u1f31d" then
--- if glyph.unicode == 127773 then
--- inspect(deltas)
--- end
applyaxis(glyph,shape,deltas,dowidth)
else
-- todo: args_are_xy_values mess .. i have to be really bored
diff --git a/tex/context/base/mkiv/font-var.mkvi b/tex/context/base/mkiv/font-var.mkvi
index fb60b711c..8520a5c32 100644
--- a/tex/context/base/mkiv/font-var.mkvi
+++ b/tex/context/base/mkiv/font-var.mkvi
@@ -50,6 +50,8 @@
\let\fontsize \defaultfontsize
\let\fontface \!!zerocount
+\installmacrostack\fontstyle
+
% we can use an indirect mapping for fontclasses (map string onto numbers) and indeed this
% is somewhat more efficient but also makes the code messy ... maybe some day ...
diff --git a/tex/context/base/mkiv/font-vfc.lua b/tex/context/base/mkiv/font-vfc.lua
new file mode 100644
index 000000000..dfe6b3afc
--- /dev/null
+++ b/tex/context/base/mkiv/font-vfc.lua
@@ -0,0 +1,123 @@
+if not modules then modules = { } end modules ['font-vfc'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv and hand-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local select, type = select, type
+local insert = table.insert
+
+local fonts = fonts
+local helpers = fonts.helpers
+
+local setmetatableindex = table.setmetatableindex
+local makeweak = table.makeweak
+
+-- Helpers dealing with virtual fonts: beware, these are final values so
+-- don't change the content of tables gotten this way!
+
+local push = { "push" }
+local pop = { "pop" }
+local dummy = { "comment" }
+
+function helpers.prependcommands(commands,...)
+ insert(commands,1,push)
+ for i=select("#",...),1,-1 do
+ local s = (select(i,...))
+ if s then
+ insert(commands,1,s)
+ end
+ end
+ insert(commands,pop)
+ return commands
+end
+
+function helpers.appendcommands(commands,...)
+ insert(commands,1,push)
+ insert(commands,pop)
+ for i=1,select("#",...) do
+ local s = (select(i,...))
+ if s then
+ insert(commands,s)
+ end
+ end
+ return commands
+end
+
+function helpers.prependcommandtable(commands,t)
+ insert(commands,1,push)
+ for i=#t,1,-1 do
+ local s = t[i]
+ if s then
+ insert(commands,1,s)
+ end
+ end
+ insert(commands,pop)
+ return commands
+end
+
+function helpers.appendcommandtable(commands,t)
+ insert(commands,1,push)
+ insert(commands,pop)
+ for i=1,#t do
+ local s = t[i]
+ if s then
+ insert(commands,s)
+ end
+ end
+ return commands
+end
+
+-- todo: maybe weak
+-- todo: maybe indirect so that we can't change them
+
+local char = setmetatableindex(function(t,k)
+ -- local v = { "char", k }
+ local v = { "slot", 0, k }
+ t[k] = v
+ return v
+end)
+
+local right = setmetatableindex(function(t,k)
+ local v = { "right", k }
+ t[k] = v
+ return v
+end)
+
+local left = setmetatableindex(function(t,k)
+ local v = { "right", -k }
+ t[k] = v
+ return v
+end)
+
+local down = setmetatableindex(function(t,k)
+ local v = { "down", k }
+ t[k] = v
+ return v
+end)
+
+local up = setmetatableindex(function(t,k)
+ local v = { "down", -k }
+ t[k] = v
+ return v
+end)
+
+-- makeweak(char)
+-- makeweak(right)
+-- makeweak(left)
+-- makeweak(up)
+-- makeweak(down)
+
+helpers.commands = utilities.storage.allocate {
+ char = char,
+ right = right,
+ left = left,
+ down = down,
+ up = up,
+ push = push,
+ pop = pop,
+ dummy = dummy,
+}
+
diff --git a/tex/context/base/mkiv/font-vir.lua b/tex/context/base/mkiv/font-vir.lua
index 03ad7fc85..c3071cac0 100644
--- a/tex/context/base/mkiv/font-vir.lua
+++ b/tex/context/base/mkiv/font-vir.lua
@@ -14,7 +14,7 @@ if not modules then modules = { } end modules ['font-vir'] = {
--
-- vf.rule vf.special vf.right vf.push vf.down vf.char vf.node vf.fontid vf.pop vf.image vf.nop
-local next = next
+local next, setmetatable, getmetatable = next, setmetatable, getmetatable
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
@@ -66,11 +66,7 @@ local combinations = { }
local combiner = { }
local whatever = allocate()
local helpers = allocate()
-local predefined = allocate {
- dummy = { "comment" },
- push = { "push" },
- pop = { "pop" },
-}
+local predefined = fonts.helpers.commands
methods.variants = variants -- todo .. wrong namespace
vf.combinations = combinations
@@ -110,8 +106,10 @@ local function combine_assign(g, name, from, to, start, force)
if not from then from, to = 0, 0xFF00 end
if not to then to = from end
if not start then start = from end
- local fc, gc = f.characters, g.characters
- local fd, gd = f.descriptions, g.descriptions
+ local fc = f.characters
+ local gc = g.characters
+ local fd = f.descriptions
+ local gd = g.descriptions
local hn = #g.fonts+1
g.fonts[hn] = { id = id } -- no need to be sparse
for i=from,to do
@@ -137,8 +135,10 @@ end
local function combine_names(g,name,force)
local f, id = constructors.readanddefine(name,g.specification.size)
if f and id then
- local fc, gc = f.characters, g.characters
- local fd, gd = f.descriptions, g.descriptions
+ local fc = f.characters
+ local gc = g.characters
+ local fd = f.descriptions
+ local gd = g.descriptions
g.fonts[#g.fonts+1] = { id = id } -- no need to be sparse
local hn = #g.fonts
for k, v in next, fc do
@@ -153,7 +153,8 @@ local function combine_names(g,name,force)
end
local combine_feature = function(g,v)
- local key, value = v[2], v[3]
+ local key = v[2]
+ local value = v[3]
if key then
if value == nil then
value = true
diff --git a/tex/context/base/mkiv/font-web.lua b/tex/context/base/mkiv/font-web.lua
index 452a8f59b..376b036f2 100644
--- a/tex/context/base/mkiv/font-web.lua
+++ b/tex/context/base/mkiv/font-web.lua
@@ -23,18 +23,30 @@ local streamwriter = readers and readers.streamwriter or utilities.files
local readstring = streamreader.readstring
local readcardinal2 = streamreader.readcardinal2
local readcardinal4 = streamreader.readcardinal4
+local getsize = streamreader.getsize
+local setposition = streamreader.setposition
+local getposition = streamreader.getposition
local writestring = streamwriter.writestring
local writecardinal4 = streamwriter.writecardinal4
local writecardinal2 = streamwriter.writecardinal2
local writebyte = streamwriter.writebyte
-local getsize = streamreader.getsize
-local setposition = streamreader.setposition
-local getposition = streamreader.getposition
-
local decompress = zlib.decompress
+directives.register("fonts.streamreader",function()
+
+ streamreader = utilities.streams
+
+ readstring = streamreader.readstring
+ readcardinal2 = streamreader.readcardinal2
+ readcardinal4 = streamreader.readcardinal4
+ getsize = streamreader.getsize
+ setposition = streamreader.setposition
+ getposition = streamreader.getposition
+
+end)
+
local infotags = {
["os/2"] = true,
["head"] = true,
diff --git a/tex/context/base/mkiv/font-xtx.lua b/tex/context/base/mkiv/font-xtx.lua
deleted file mode 100644
index 494ac00a9..000000000
--- a/tex/context/base/mkiv/font-xtx.lua
+++ /dev/null
@@ -1,97 +0,0 @@
-if not modules then modules = { } end modules ['luatex-fonts-def'] = {
- version = 1.001,
- comment = "companion to luatex-*.tex",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-if context then
- texio.write_nl("fatal error: this module is not for context")
- os.exit()
-end
-
-local fonts = fonts
-
--- A bit of tuning for definitions.
-
-fonts.constructors.namemode = "specification" -- somehow latex needs this (changed name!) => will change into an overload
-
--- tricky: we sort of bypass the parser and directly feed all into
--- the sub parser
-
-function fonts.definers.getspecification(str)
- return "", str, "", ":", str
-end
-
--- the generic name parser (different from context!)
-
-local list = { }
-
-local function issome () list.lookup = 'name' end -- xetex mode prefers name (not in context!)
-local function isfile () list.lookup = 'file' end
-local function isname () list.lookup = 'name' end
-local function thename(s) list.name = s end
-local function issub (v) list.sub = v end
-local function iscrap (s) list.crap = string.lower(s) end
-local function iskey (k,v) list[k] = v end
-local function istrue (s) list[s] = true end
-local function isfalse(s) list[s] = false end
-
-local P, S, R, C = lpeg.P, lpeg.S, lpeg.R, lpeg.C
-
-local spaces = P(" ")^0
-local namespec = (1-S("/:("))^0 -- was: (1-S("/: ("))^0
-local crapspec = spaces * P("/") * (((1-P(":"))^0)/iscrap) * spaces
-local filename_1 = P("file:")/isfile * (namespec/thename)
-local filename_2 = P("[") * P(true)/isname * (((1-P("]"))^0)/thename) * P("]")
-local fontname_1 = P("name:")/isname * (namespec/thename)
-local fontname_2 = P(true)/issome * (namespec/thename)
-local sometext = (R("az","AZ","09") + S("+-.{}"))^1
-local truevalue = P("+") * spaces * (sometext/istrue)
-local falsevalue = P("-") * spaces * (sometext/isfalse)
-local keyvalue = (C(sometext) * spaces * P("=") * spaces * C(sometext))/iskey
-local somevalue = sometext/istrue
-local subvalue = P("(") * (C(P(1-S("()"))^1)/issub) * P(")") -- for Kim
-local option = spaces * (keyvalue + falsevalue + truevalue + somevalue) * spaces
-local options = P(":") * spaces * (P(";")^0 * option)^0
-
-local pattern = (filename_1 + filename_2 + fontname_1 + fontname_2) * subvalue^0 * crapspec^0 * options^0
-
-local function colonized(specification) -- xetex mode
- list = { }
- lpeg.match(pattern,specification.specification)
- list.crap = nil -- style not supported, maybe some day
- if list.name then
- specification.name = list.name
- list.name = nil
- end
- if list.lookup then
- specification.lookup = list.lookup
- list.lookup = nil
- end
- if list.sub then
- specification.sub = list.sub
- list.sub = nil
- end
- specification.features.normal = fonts.handlers.otf.features.normalize(list)
- return specification
-end
-
-fonts.definers.registersplit(":",colonized,"cryptic")
-fonts.definers.registersplit("", colonized,"more cryptic") -- catches \font\text=[names]
-
-function fonts.definers.applypostprocessors(tfmdata)
- local postprocessors = tfmdata.postprocessors
- if postprocessors then
- for i=1,#postprocessors do
- local extrahash = postprocessors[i](tfmdata) -- after scaling etc
- if type(extrahash) == "string" and extrahash ~= "" then
- -- e.g. a reencoding needs this
- extrahash = string.gsub(lower(extrahash),"[^a-z]","-")
- tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash)
- end
- end
- end
- return tfmdata
-end
diff --git a/tex/context/base/mkiv/good-ctx.lua b/tex/context/base/mkiv/good-ctx.lua
index 00e4ed78d..82ef25e29 100644
--- a/tex/context/base/mkiv/good-ctx.lua
+++ b/tex/context/base/mkiv/good-ctx.lua
@@ -29,14 +29,10 @@ local registerotffeature = fonts.handlers.otf.features.register
local fontgoodies = fonts.goodies or { }
-local glyph_code = nodes.nodecodes.glyph
-
local nuts = nodes.nuts
local tonut = nuts.tonut
-local getfont = nuts.getfont
-local getchar = nuts.getchar
local getattr = nuts.getattr
-local traverse_id = nuts.traverse_id
+local nextglyph = nuts.traversers.glyph
-- colorschemes
@@ -100,10 +96,10 @@ local function setcolorscheme(tfmdata,scheme)
end
end
if privatestoo then
- local private = fonts.constructors.privateoffset
- local descriptions = tfmdata.descriptions
+ local privateoffset = fonts.constructors.privateoffset
+ local descriptions = tfmdata.descriptions
for unicode, data in next, characters do
- if unicode >= private then
+ if unicode >= privateoffset then
if not reverse[unicode] then
local d = descriptions[unicode]
if d then
@@ -128,68 +124,9 @@ local function setcolorscheme(tfmdata,scheme)
end
local fontproperties = fonts.hashes.properties
-
local a_colorscheme = attributes.private('colorscheme')
local setnodecolor = nodes.tracers.colors.set
-
--- function colorschemes.coloring(head)
--- local lastfont, lastscheme
--- local done = false
--- for n in traverse_id(glyph_code,tonut(head)) do
--- local a = getattr(n,a_colorscheme)
--- if a then
--- local f = getfont(n)
--- if f ~= lastfont then
--- lastscheme = fontproperties[f].colorscheme
--- lastfont = f
--- end
--- if lastscheme then
--- local sc = lastscheme[getchar(n)]
--- if sc then
--- done = true
--- setnodecolor(n,"colorscheme:"..a..":"..sc) -- slow
--- end
--- end
--- end
--- end
--- return head, done
--- end
-
--- seldom used, mostly in manuals, so non critical .. anyhow, somewhat faster:
-
--- function colorschemes.coloring(head)
--- local lastfont = nil
--- local lastattr = nil
--- local lastscheme = nil
--- local lastprefix = nil
--- local done = nil
--- for n in traverse_id(glyph_code,tonut(head)) do
--- local a = getattr(n,a_colorscheme)
--- if a then
--- if a ~= lastattr then
--- lastattr = a
--- lastprefix = "colorscheme:" .. a .. ":"
--- end
--- local f = getfont(n)
--- if f ~= lastfont then
--- lastfont = f
--- lastscheme = fontproperties[f].colorscheme
--- end
--- if lastscheme then
--- local sc = lastscheme[getchar(n)]
--- if sc then
--- setnodecolor(n,lastprefix .. sc) -- slow
--- done = true
--- end
--- end
--- end
--- end
--- return head, done
--- end
-
--- ok, in case we have hundreds of pages colored:
-
-local cache = { } -- this could be a weak table
+local cache = { } -- this could be a weak table
setmetatableindex(cache,function(t,a)
local v = { }
@@ -207,11 +144,9 @@ function colorschemes.coloring(head)
local lastattr = nil
local lastcache = nil
local lastscheme = nil
- local done = nil
- for n in traverse_id(glyph_code,tonut(head)) do
+ for n, char, f in nextglyph, head do
local a = getattr(n,a_colorscheme)
if a then
- local f = getfont(n)
if f ~= lastfont then
lastfont = f
lastscheme = fontproperties[f].colorscheme
@@ -221,19 +156,18 @@ function colorschemes.coloring(head)
lastcache = cache[a]
end
if lastscheme then
- local sc = lastscheme[getchar(n)]
+ local sc = lastscheme[char]
if sc then
setnodecolor(n,lastcache[sc]) -- we could inline this one
- done = true
end
end
end
end
- return head, done
+ return head
end
function colorschemes.enable()
- nodes.tasks.appendaction("processors","fonts","fonts.goodies.colorschemes.coloring")
+ nodes.tasks.enableaction("processors","fonts.goodies.colorschemes.coloring")
function colorschemes.enable() end
end
diff --git a/tex/context/base/mkiv/grph-epd.lua b/tex/context/base/mkiv/grph-epd.lua
index 7855ce891..f8fa62953 100644
--- a/tex/context/base/mkiv/grph-epd.lua
+++ b/tex/context/base/mkiv/grph-epd.lua
@@ -8,25 +8,26 @@ if not modules then modules = { } end modules ['grph-epd'] = {
local variables = interfaces.variables
local settings_to_hash = utilities.parsers.settings_to_hash
+local codeinjections = backends.pdf.codeinjections
--- todo: page, name, file, url
+local trace = false trackers.register("figures.merging", function(v) trace = v end)
--- I have some experimental code for including comments and fields but it's
--- unfinished and not included as it was just a proof of concept to get some idea
--- about what is needed and possible. But the placeholders are here already.
-
-local codeinjections = backends.codeinjections
+local report = logs.reporter("backend","merging")
local function mergegoodies(optionlist)
local options = settings_to_hash(optionlist)
- local all = options[variables.all] or options[variables.yes]
- if all or options[variables.reference] then
+ local yes = options[variables.yes]
+ local all = options[variables.all]
+ if next(options) then
+ report("% t",table.sortedkeys(options))
+ end
+ if all or yes or options[variables.reference] then
codeinjections.mergereferences()
end
if all or options[variables.comment] then
codeinjections.mergecomments()
end
- if all or options[variables.bookmark] then
+ if all or yes or options[variables.bookmark] then
codeinjections.mergebookmarks()
end
if all or options[variables.field] then
@@ -39,6 +40,7 @@ local function mergegoodies(optionlist)
end
function figures.mergegoodies(optionlist)
+ -- todo: we can use runtoks instead
context.stepwise(function()
-- we use stepwise because we might need to define symbols
-- for stamps that have no default appearance
diff --git a/tex/context/base/mkiv/grph-inc.lua b/tex/context/base/mkiv/grph-inc.lua
index f2d7847eb..1e5c30d44 100644
--- a/tex/context/base/mkiv/grph-inc.lua
+++ b/tex/context/base/mkiv/grph-inc.lua
@@ -6,6 +6,11 @@ if not modules then modules = { } end modules ['grph-inc'] = {
license = "see context related readme files"
}
+-- todo: in pdfe: pdfe.copyappearance(document,objnum)
+--
+-- local im = createimage { filename = fullname }
+-- local on = images.flushobject(im,document.__xrefs__[AP])
+
-- todo: files are sometimes located twice
-- todo: empty filename or only suffix always false (not found)
-- lowercase types
@@ -40,17 +45,16 @@ run TeX code from within Lua. Some more functionality will move to Lua.
-- todo: store loaded pages per pdf file someplace
-local tonumber, tostring, next = tonumber, tostring, next
+local tonumber, tostring, next, unpack = tonumber, tostring, next, unpack
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
local longtostring = string.longtostring
local contains = table.contains
-local sortedhash = table.sortedhash
+local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys
local concat, insert, remove = table.concat, table.insert, table.remove
local todimen = string.todimen
local collapsepath = file.collapsepath
local formatters = string.formatters
-local formatcolumns = utilities.formatters.formatcolumns
-local max, odd = math.max, math.odd
+local odd = math.odd
local P, R, S, Cc, C, Cs, Ct, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.Cc, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.match
@@ -60,7 +64,10 @@ local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
local replacetemplate = utilities.templates.replace
-local images = img
+local bpfactor = number.dimenfactors.bp
+
+images = images or { }
+local images = images
local hasscheme = url.hasscheme
local urlhashed = url.hashed
@@ -104,7 +111,7 @@ local v_local = variables["local"]
local v_default = variables.default
local v_auto = variables.auto
-local maxdimen = 0x3FFFFFFF -- 2^30-1
+local maxdimen = tex.magicconstants.maxdimen -- 0x3FFFFFFF -- 2^30-1
local ctx_doscalefigure = context.doscalefigure
local ctx_relocateexternalfigure = context.relocateexternalfigure
@@ -120,11 +127,11 @@ function checkimage(figure)
local width = figure.width
local height = figure.height
if width <= 0 or height <= 0 then
- report_inclusion("image %a has bad dimensions (%p,%p), discarding",figure.filename,width,height)
+ report_inclusion("image %a has bad dimensions (%p,%p), discarding",figure.filename or "?",width,height)
return false, "bad dimensions"
end
- local xres = figure.xres
- local yres = figure.yres
+ -- local xres = figure.xres
+ -- local yres = figure.yres
local changes = false
if height > width then
if height > maxdimen then
@@ -150,14 +157,117 @@ function checkimage(figure)
end
end
---- some extra img functions --- can become luat-img.lua
+--- begin of mapping / this will become graphics & code|nodeinjections but not this year
+
+local __img__ = type(img) == "table" and img or { }
+images.__img__ =__img__
+
+local imgnew = __img__.new
+local imgscan = __img__.scan
+local imgcopy = __img__.copy
+local imgwrap = __img__.node
+local imgembed = __img__.immediatewrite
+
+if imgnew then
+ -- catch (actually we should be less picky in img)
+ local __img__new__ = img_new
+ imgnew = function(t)
+ t.kind = nil
+ return __img__new__(t)
+ end
+end
+
+updaters.register("backend.update",function()
+ local img = images.__img__
+ imgnew = img.new
+ imgscan = img.scan
+ imgcopy = img.copy
+ imgwrap = img.wrap
+ imgembed = img.embed
+end)
+
+local imagekeys = { -- only relevant ones
+ "width", "height", "depth", "bbox",
+ "colordepth", "colorspace",
+ "filename", "filepath", "visiblefilename",
+ "imagetype", "stream",
+ "index", "objnum",
+ "pagebox", "page", "pages",
+ "rotation", "transform",
+ "xsize", "ysize", "xres", "yres",
+}
+
+local imagesizes = {
+ art = true, bleed = true, crop = true,
+ media = true, none = true, trim = true,
+}
+
+local imagetypes = { [0] =
+ "none",
+ "pdf", "png", "jpg", "jp2", "jbig2",
+ "stream", "memstream",
+}
+
+imagetypes = table.swapped(imagetypes,imagetypes)
+
+images.keys = imagekeys
+images.types = imagetypes
+images.sizes = imagesizes
+
+-- new interface
+
+local function createimage(specification)
+ return imgnew(specification)
+end
+
+local function copyimage(specification)
+ return imgcopy(specification)
+end
+
+local function scanimage(specification)
+ return imgscan(specification)
+end
+
+local function embedimage(specification)
+ -- write the image to file
+ return imgembed(specification)
+end
+
+local function wrapimage(specification)
+ -- create an image rule
+ return imgwrap(specification)
+end
+
+images.create = createimage
+images.scan = scanimage
+images.copy = copyimage
+images.wrap = wrapimage
+images.embed = embedimage
+
+-- now we reimplement img:
+
+img = {
+ new = createimage,
+ scan = scanimage,
+ copy = copyimage,
+ node = wrapimage,
+ write = function(specification) context(wrapimage(specification)) end,
+ immediatewrite = embedimage,
+ immediatewriteobject = function() end, -- not upported, experimental anyway
+ boxes = function() return sortedkeys(imagesizes) end,
+ fields = function() return imagekeys end,
+ types = function() return { unpack(imagetypes,0,#imagetypes) } end,
+}
-local allimagekeys = images.keys()
+-- end of copies / mapping
local function imagetotable(imgtable)
+ if type(imgtable) == "table" then
+ return copy(imgtable)
+ end
local result = { }
- for k=1,#allimagekeys do
- local key = allimagekeys[k]
+ for k=1,#imagekeys do
+ local key = imagekeys[k]
result[key] = imgtable[key]
end
return result
@@ -171,41 +281,24 @@ function images.print(i,...)
return table.print(imagetotable(i),...)
end
-function images.clone(i,data)
- i.width = data.width or i.width
- i.height = data.height or i.height
- -- attr etc
- return i
-end
-
-local validsizes = table.tohash(images.boxes())
-local validtypes = table.tohash(images.types())
-
local function checkimagesize(size)
if size then
size = gsub(size,"box","")
- return validsizes[size] and size or "crop"
+ return imagesizes[size] and size or "crop"
else
return "crop"
end
end
-local newimage = images.new
-local scanimage = images.scan
-local copyimage = images.copy
-local cloneimage = images.clone
-local imagetonode = images.node
-
-images.check = checkimage
-images.checksize = checkimagesize
-images.tonode = imagetonode
-images.totable = imagetotable
+images.check = checkimage
+images.checksize = checkimagesize
+images.totable = imagetotable
-local indexed = { }
-
-function images.ofindex(n)
- return indexed[n]
-end
+-- local indexed = { }
+--
+-- function images.ofindex(n)
+-- return indexed[n]
+-- end
--- we can consider an grph-ini file
@@ -372,22 +465,30 @@ function figures.setorder(list) -- can be table or string
end
end
+local function guessfromstring(str)
+ if str then
+ for i=1,#figures_magics do
+ local pattern = figures_magics[i]
+ if lpegmatch(pattern.pattern,str) then
+ local format = pattern.format
+ if trace_figures then
+ report_inclusion("file %a has format %a",filename,format)
+ end
+ return format
+ end
+ end
+ end
+end
+
+figures.guessfromstring = guessfromstring
+
function figures.guess(filename)
local f = io.open(filename,'rb')
if f then
local str = f:read(100)
f:close()
if str then
- for i=1,#figures_magics do
- local pattern = figures_magics[i]
- if lpegmatch(pattern.pattern,str) then
- local format = pattern.format
- if trace_figures then
- report_inclusion("file %a has format %a",filename,format)
- end
- return format
- end
- end
+ return guessfromstring(str)
end
end
end
@@ -571,6 +672,7 @@ function figures.initialize(request)
request.cache = request.cache ~= "" and request.cache
request.prefix = request.prefix ~= "" and request.prefix
request.format = request.format ~= "" and request.format
+ request.compact = request.compact == v_yes
table.merge(figuredata.request,request)
end
return figuredata
@@ -818,7 +920,7 @@ local function register(askedname,specification)
end
elseif io.exists(oldname) then
report_inclusion("file %a is bugged",oldname)
- if format and validtypes[format] then
+ if format and imagetypes[format] then
specification.fullname = oldname
end
specification.converted = false
@@ -827,13 +929,13 @@ local function register(askedname,specification)
end
end
if format then
- local found = figures_suffixes[format] -- validtypes[format]
+ local found = figures_suffixes[format]
if not found then
specification.found = false
if trace_figures then
report_inclusion("format %a is not supported",format)
end
- elseif validtypes[format] then
+ elseif imagetypes[format] then
specification.found = true
if trace_figures then
report_inclusion("format %a natively supported by backend",format)
@@ -1362,15 +1464,18 @@ end
local pagecount = { }
function checkers.generic(data)
- local dr, du, ds = data.request, data.used, data.status
- local name = du.fullname or "unknown generic"
- local page = du.page or dr.page
- local size = dr.size or "crop"
- local color = dr.color or "natural"
- local mask = dr.mask or "none"
- local conversion = dr.conversion
- local resolution = dr.resolution
- local arguments = dr.arguments
+ local dr, du, ds = data.request, data.used, data.status
+ local name = du.fullname or "unknown generic"
+ local page = du.page or dr.page
+ local size = dr.size or "crop"
+ local color = dr.color or "natural"
+ local mask = dr.mask or "none"
+ local conversion = dr.conversion
+ local resolution = dr.resolution
+ local arguments = dr.arguments
+ local scanimage = dr.scanimage or scanimage
+ local userpassword = dr.userpassword
+ local ownerpassword = dr.ownerpassword
if not conversion or conversion == "" then
conversion = "default"
end
@@ -1390,22 +1495,29 @@ function checkers.generic(data)
resolution,
arguments
)
+ --
local figure = figures_loaded[hash]
if figure == nil then
- figure = newimage {
+ figure = createimage {
filename = name,
page = page,
pagebox = dr.size,
keepopen = dr.keepopen or false,
+ userpassword = userpassword,
+ ownerpassword = ownerpassword,
-- visiblefilename = "", -- this prohibits the full filename ending up in the file
}
codeinjections.setfigurecolorspace(data,figure)
codeinjections.setfiguremask(data,figure)
if figure then
- -- new, bonus check
+ -- new, bonus check (a bogus check in lmtx)
if page and page > 1 then
- local f = scanimage{ filename = name }
- if f.page and f.pages < page then
+ local f = scanimage {
+ filename = name,
+ userpassword = userpassword,
+ ownerpassword = ownerpassword,
+ }
+ if f and f.page and f.pages < page then
report_inclusion("no page %i in %a, using page 1",page,name)
page = 1
figure.page = page
@@ -1418,6 +1530,10 @@ function checkers.generic(data)
ds.found = false
ds.error = true
end
+ if figure.attr and not f.attr then
+ -- tricky as img doesn't allow it
+ f.attr = figure.attr
+ end
figure = f
end
local f, d = codeinjections.setfigurealternative(data,figure)
@@ -1459,6 +1575,11 @@ function figures.getrealpage(index)
return pofimages[index] or 0
end
+local function updatepage(specification)
+ local n = specification.n
+ pofimages[n] = pofimages[n] or tex.count.realpageno -- so when reused we register the first one only
+end
+
function includers.generic(data)
local dr, du, ds = data.request, data.used, data.status
-- here we set the 'natural dimensions'
@@ -1472,10 +1593,13 @@ function includers.generic(data)
-- height = dr.height,
-- }
if figure == nil then
- figure = ds.private
+ figure = ds.private -- the img object
if figure then
- figure = copyimage(figure)
- figure = figure and cloneimage(figure,data.request) or false
+ figure = (dr.copyimage or copyimage)(figure)
+ if figure then
+ figure.width = dr.width or figure.width
+ figure.height = dr.height or figure.height
+ end
end
figures_used[hash] = figure
end
@@ -1483,16 +1607,15 @@ function includers.generic(data)
local nr = figures.boxnumber
nofimages = nofimages + 1
ds.pageindex = nofimages
- local image = imagetonode(figure)
- local pager = new_latelua(function()
- pofimages[nofimages] = pofimages[nofimages] or tex.count.realpageno -- so when reused we register the first one only
- end)
+ local image = wrapimage(figure)
+ local pager = new_latelua { action = updatepage, n = nofimages }
image.next = pager
pager.prev = image
- local box = hpack(image) -- imagetonode(figure) not longer valid
-
- indexed[figure.index] = figure
- box.width, box.height, box.depth = figure.width, figure.height, 0 -- new, hm, tricky, we need to do that in tex (yet)
+ local box = hpack(image)
+ -- indexed[figure.index] = figure
+ box.width = figure.width
+ box.height = figure.height
+ box.depth = 0
texsetbox(nr,box)
ds.objectnumber = figure.objnum
ctx_relocateexternalfigure()
@@ -1546,7 +1669,7 @@ function checkers.mov(data)
nodeinjections.insertmovie {
width = width,
height = height,
- factor = number.dimenfactors.bp,
+ factor = bpfactor,
["repeat"] = dr["repeat"],
controls = dr.controls,
preview = dr.preview,
@@ -1916,8 +2039,10 @@ function figures.getinfo(name,page)
end
if name.name then
local data = figures.push(name)
- figures.identify()
- figures.check()
+ data = figures.identify(data)
+ if data.status and data.status.status > 0 then
+ data = figures.check(data)
+ end
figures.pop()
return data
end
@@ -1961,8 +2086,11 @@ implement {
{ "arguments" },
{ "repeat" },
{ "transform" },
+ { "compact" },
{ "width", "dimen" },
{ "height", "dimen" },
+ { "userpassword" },
+ { "ownerpassword" },
}
}
}
diff --git a/tex/context/base/mkiv/grph-inc.mkiv b/tex/context/base/mkiv/grph-inc.mkiv
index 677883fbb..20e7c11a6 100644
--- a/tex/context/base/mkiv/grph-inc.mkiv
+++ b/tex/context/base/mkiv/grph-inc.mkiv
@@ -20,7 +20,15 @@
\writestatus{loading}{ConTeXt Graphic Macros / Figure Inclusion}
-\registerctxluafile{grph-inc}{}
+\ifcase\contextlmtxmode
+ \registerctxluafile{grph-inc}{}
+\else
+ \registerctxluafile{grph-img}{}
+ \registerctxluafile{grph-inc}{}
+ \registerctxluafile{grph-bmp}{}
+ \registerctxluafile{grph-chk}{}
+\fi
+
\registerctxluafile{grph-con}{}
\registerctxluafile{grph-fil}{}
\registerctxluafile{grph-mem}{}
@@ -32,7 +40,7 @@
%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 is delegated to the \LUA\ end. There is not 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.
@@ -105,6 +113,9 @@
\c!align =\v!none, % New, for Tacos extremely large graphics.
\c!crossreference =\v!no,
\c!transform =\v!auto,
+ \c!userpassword =,
+ \c!ownerpassword =,
+ \c!compact =,
]
%D Defining figures.
@@ -201,7 +212,7 @@
{\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}}%
+ {\dodoglobal\setvalue{\??externalfigureinstance#1}{\grph_include_setup{#2}{#3}{#4}}%
\grph_include_analyze_collection[#2][#4]}
% inclusion
@@ -317,27 +328,30 @@
%
\dostarttagged\t!image\empty
\clf_figure_push {
- name {\p_grph_include_name}%
- label {\ifx\p_label\empty\p_grph_include_label\else\p_label\fi}%
- page {\externalfigureparameter\c!page}%
- file {\externalfigureparameter\c!file}%
- 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 {\externalfigureparameter\c!color}% unprocessed raw key
- arguments {\externalfigureparameter\c!arguments}% used for converters
- repeat {\externalfigureparameter\c!repeat}%
- transform {\externalfigureparameter\c!transform}%
+ name {\p_grph_include_name}%
+ label {\ifx\p_label\empty\p_grph_include_label\else\p_label\fi}%
+ page {\externalfigureparameter\c!page}%
+ file {\externalfigureparameter\c!file}%
+ 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 {\externalfigureparameter\c!color}% unprocessed raw key
+ arguments {\externalfigureparameter\c!arguments}% used for converters
+ repeat {\externalfigureparameter\c!repeat}%
+ transform {\externalfigureparameter\c!transform}%
+ compact {\externalfigureparameter\c!compact}% experiment, share fonts
+ userpassword {\externalfigureparameter\c!userpassword}%
+ ownerpassword{\externalfigureparameter\c!ownerpassword}%
\ifx\p_width\empty \else
width \dimexpr\p_width\relax
\fi
@@ -589,9 +603,9 @@
\def\grph_include_set_mode
{\ifcase\figurestatus
- \global\resetsystemmode\v!figure % todo, also: \v!resource
+ \globalresetsystemmode\v!figure % todo, also: \v!resource
\else
- \global\setsystemmode \v!figure % todo, also: \v!resource
+ \globalsetsystemmode \v!figure % todo, also: \v!resource
\fi}
\appendtoks
@@ -641,10 +655,41 @@
\unexpanded\def\docheckfiguremps #1{\global\setbox\foundexternalfigure\vpack{\convertMPtoPDF{#1}11}}
\unexpanded\def\docheckfiguremprun #1#2{\global\setbox\foundexternalfigure\vpack{\useMPrun{#1}{#2}}}
-\unexpanded\def\relocateexternalfigure % easier here than in lua
+% \unexpanded\def\relocateexternalfigure % easier here than in lua
+% {\global\setbox\foundexternalfigure\vpack to \ht\foundexternalfigure\bgroup
+% \vss
+% \ht\foundexternalfigure\zeropoint
+% \hpack to \wd\foundexternalfigure\bgroup
+% \box\foundexternalfigure
+% \hss
+% \egroup
+% \egroup}
+
+\unexpanded\def\relocateexternalfigure
{\global\setbox\foundexternalfigure\vpack to \ht\foundexternalfigure\bgroup
- \vss
+ %
+ % The \vss can (!) introduce 1 sp excess visible in xform which in itself
+ % is not that important but some don't like these cosmetic side effects, for
+ % instance we can get:
+ %
+ % vss : \vbox(845.1575+0.0)x597.23125, glue set 845.15747fil, direction TLT
+ % vskip : \vbox(845.1575+0.0)x597.23125, direction TLT
+ %
+ % or
+ %
+ % 1 0 0 1 0 0.00003 cm
+ % 1 0 0 1 0 0 cm
+ %
+ % This is a known property of using glue and can even depend on the architecture
+ % (float implementation). Anyway, let's for now use a skip. Of course this can
+ % shift the issue elsewhere, as vss is used a lot elsewhere.
+ %
+ % \vss
+ \vkern\ht\foundexternalfigure
+ %
+ % \parfillskip\zeropoint
\ht\foundexternalfigure\zeropoint
+ \dp\foundexternalfigure\zeropoint
\hpack to \wd\foundexternalfigure\bgroup
\box\foundexternalfigure
\hss
diff --git a/tex/context/base/mkiv/grph-mem.lua b/tex/context/base/mkiv/grph-mem.lua
index bb48ae8d5..ff3548350 100644
--- a/tex/context/base/mkiv/grph-mem.lua
+++ b/tex/context/base/mkiv/grph-mem.lua
@@ -20,67 +20,143 @@ local gsub = string.gsub
local report = logs.reporter("memstream")
local trace = false trackers.register ("graphics.memstreams", function(v) trace = v end)
local data = { }
-local opened = { }
-local function setmemstream(name,stream,once)
- if once and data[name] then
+if pdfe then
+
+ local function setmemstream(name,stream,once)
+ if once and data[name] then
+ if trace then
+ report("not overloading %a",name) --
+ end
+ return data[name]
+ end
+ local kind = figures.guessfromstring(stream)
+ local identifier = false
+ if kind == "pdf" then
+ identifier = pdfe.new(stream,#stream,name)
+ if not identifier then
+ report("no valid pdf stream %a",name)
+ elseif trace then
+ report("setting %a with identifier %a",name,identifier)
+ end
+ else
+ identifier = "m_k_i_v_memstream_" .. name .. "." .. kind
+ io.savedata(identifier,stream)
+ end
+ if not identifier then
+ identifier = "invalid-memstream"
+ end
+ data[name] = identifier
+ return identifier
+ end
+
+ resolvers.setmemstream = setmemstream
+
+ function resolvers.finders.memstream(specification)
+ local name = specification.path
+ local identifier = data[name]
+ if identifier then
+ if trace then
+ report("reusing %a with identifier %a",name,identifier)
+ end
+ return identifier
+ end
+ local stream = io.loaddata(name)
+ if stream and stream ~= "" then
+ return setmemstream(name,stream)
+ end
if trace then
- report("not overloading %a",name) --
+ report("no valid memstream %a",name)
end
- return data[name]
+ return resolvers.finders.notfound()
end
- local memstream, identifier = epdf.openMemStream(stream,#stream,name)
- if not identifier then
- report("no valid stream %a",name)
- identifier = "invalid-memstream"
- elseif trace then
- report("setting %a with identifier %a",name,identifier)
+
+ local flush = { }
+
+ function resolvers.resetmemstream(name,afterpage)
+ if afterpage then
+ flush[#flush+1] = name
+ end
end
- data [name] = identifier
- opened[name] = memstream
- return identifier
-end
-resolvers.setmemstream = setmemstream
+ luatex.registerpageactions(function()
+ if #flush > 0 then
+ for i=1,#flush do
+ local identifier = data[name]
+ if identifier then
+ os.remove(identifier)
+ data[name] = nil
+ end
+ end
+ flush = { }
+ end
+ end)
+
+else
-function resolvers.finders.memstream(specification)
- local name = specification.path
- local identifier = data[name]
- if identifier then
- if trace then
- report("reusing %a with identifier %a",name,identifier)
+ local opened = { }
+
+ local function setmemstream(name,stream,once)
+ if once and data[name] then
+ if trace then
+ report("not overloading %a",name) --
+ end
+ return data[name]
end
+ local memstream, identifier = epdf.openMemStream(stream,#stream,name)
+ if not identifier then
+ report("no valid stream %a",name)
+ identifier = "invalid-memstream"
+ elseif trace then
+ report("setting %a with identifier %a",name,identifier)
+ end
+ data [name] = identifier
+ opened[name] = memstream
return identifier
end
- local stream = io.loaddata(name)
- if not stream or stream == "" then
- if trace then
- report("no valid file %a",name)
+
+ resolvers.setmemstream = setmemstream
+
+ function resolvers.finders.memstream(specification)
+ local name = specification.path
+ local identifier = data[name]
+ if identifier then
+ if trace then
+ report("reusing %a with identifier %a",name,identifier)
+ end
+ return identifier
+ end
+ local stream = io.loaddata(name)
+ if not stream or stream == "" then
+ if trace then
+ report("no valid file %a",name)
+ end
+ return resolvers.finders.notfound()
+ else
+ return setmemstream(name,stream)
end
- return resolvers.finders.notfound()
- else
- return setmemstream(name,stream)
end
-end
-local flush = { }
+ local flush = { }
-function resolvers.resetmemstream(name,afterpage)
- if afterpage then
- flush[#flush+1] = name
- else
- opened[name] = nil
+ function resolvers.resetmemstream(name,afterpage)
+ if afterpage then
+ flush[#flush+1] = name
+ else
+ opened[name] = nil
+ end
end
-end
-luatex.registerpageactions(function()
- if #flush > 0 then
- for i=1,#flush do
- opened[flush[i]] = nil -- we keep of course data[name] because of reuse
+ luatex.registerpageactions(function()
+ if #flush > 0 then
+ for i=1,#flush do
+ opened[flush[i]] = nil -- we keep of course data[name] because of reuse
+ end
+ flush = { }
end
- flush = { }
- end
-end)
+ end)
+
+end
figures.identifiers.list[#figures.identifiers.list+1] = function(specification)
local name = specification.request.name
diff --git a/tex/context/base/mkiv/grph-pat.lua b/tex/context/base/mkiv/grph-pat.lua
index 89b29906d..e38a9a674 100644
--- a/tex/context/base/mkiv/grph-pat.lua
+++ b/tex/context/base/mkiv/grph-pat.lua
@@ -15,7 +15,7 @@ local texsetbox = tex.setbox
local texgetbox = tex.getbox
local nodepool = nodes.pool
-local new_literal = nodepool.pdforiginliteral -- really ?
+local new_literal = nodepool.originliteral -- really ?
local new_hlist = nodepool.hlist
local names = { }
@@ -37,7 +37,7 @@ interfaces.implement {
if not name or name == "" then
return
end
- nodes.handlers.finalize(box,"object")
+ nodes.handlers.finalizebox(number)
names[name] = lpdf.registerpattern {
number = number,
width = specification.width or box.width,
diff --git a/tex/context/base/mkiv/grph-rul.lua b/tex/context/base/mkiv/grph-rul.lua
index 03f678973..08edade1f 100644
--- a/tex/context/base/mkiv/grph-rul.lua
+++ b/tex/context/base/mkiv/grph-rul.lua
@@ -8,33 +8,48 @@ if not modules then modules = { } end modules ['grph-rul'] = {
local tonumber, next, type = tonumber, next, type
-local attributes = attributes
-local nodes = nodes
-local context = context
+local attributes = attributes
+local nodes = nodes
+local context = context
-local ruleactions = nodes.rules.ruleactions
-local userrule = nodes.rules.userrule
-local bpfactor = number.dimenfactors.bp
-local pdfprint = pdf.print
+local bpfactor = number.dimenfactors.bp
-local current_attr = nodes.current_attr
-local setfield = nodes.setfield
+local nuts = nodes.nuts
+local userrule = nuts.rules.userrule
+local outlinerule = nuts.pool.outlinerule
+local ruleactions = nuts.rules.ruleactions
-local getattribute = tex.getattribute
+local setattrlist = nuts.setattrlist
+local setattr = nuts.setattr
+local tonode = nuts.tonode
-local a_color = attributes.private('color')
-local a_transparency = attributes.private('transparency')
-local a_colormodel = attributes.private('colormodel')
+local getattribute = tex.getattribute
-local mpcolor = attributes.colors.mpcolor
+local lefttoright_code = nodes.dirvalues.lefttoright
-local trace_mp = false trackers.register("rules.mp", function(v) trace_mp = v end)
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local a_colormodel = attributes.private('colormodel')
-local report_mp = logs.reporter("rules","mp")
+local mpcolor = attributes.colors.mpcolor
-local floor = math.floor
-local getrandom = utilities.randomizer.get
-local formatters = string.formatters
+local trace_mp = false trackers.register("rules.mp", function(v) trace_mp = v end)
+
+local report_mp = logs.reporter("rules","mp")
+
+local floor = math.floor
+local getrandom = utilities.randomizer.get
+local formatters = string.formatters
+
+-- This is very pdf specific. Maybe move some to lpdf-rul.lua some day.
+
+local pdfprint
+
+pdfprint = function(...) pdfprint = lpdf.print return pdfprint(...) end
+
+updaters.register("backend.update",function()
+ pdfprint = lpdf.print
+end)
do
@@ -97,19 +112,18 @@ def RuleColor = %color% enddef ;
ruleactions.mp = function(p,h,v,i,n)
local name = p.name or "fake:rest"
local code = (predefined[name] or predefined["fake:rest"]) {
- data = p.data or "",
- width = p.width * bpfactor,
- height = p.height * bpfactor,
- depth = p.depth * bpfactor,
- factor = (p.factor or 0) * bpfactor, -- needs checking
- offset = p.offset or 0,
- line = (p.line or 65536) * bpfactor,
- color = mpcolor(p.ma,p.ca,p.ta),
- option = p.option or "",
- direction = p.direction or "TLT",
- h = h * bpfactor,
- v = v * bpfactor,
-
+ data = p.data or "",
+ width = p.width * bpfactor,
+ height = p.height * bpfactor,
+ depth = p.depth * bpfactor,
+ factor = (p.factor or 0) * bpfactor, -- needs checking
+ offset = p.offset or 0,
+ line = (p.line or 65536) * bpfactor,
+ color = mpcolor(p.ma,p.ca,p.ta),
+ option = p.option or "",
+ direction = p.direction or lefttoright_code,
+ h = h * bpfactor,
+ v = v * bpfactor,
}
if not initialized then
initialized = true
@@ -134,14 +148,28 @@ do
local f_rectangle = formatters["%.6F w %.6F %.6F %.6F %.6F re %s"]
local f_baselined = formatters["%.6F w %.6F %.6F %.6F %.6F re s %.6F %.6F m %.6F %.6F l s"]
local f_dashlined = formatters["%.6F w %.6F %.6F %.6F %.6F re s [%.6F %.6F] 2 d %.6F %.6F m %.6F %.6F l s"]
- local f_radtangle = formatters[ [[
- %.6F w %.6F %.6F m
- %.6F %.6F l %.6F %.6F %.6F %.6F y
- %.6F %.6F l %.6F %.6F %.6F %.6F y
- %.6F %.6F l %.6F %.6F %.6F %.6F y
- %.6F %.6F l %.6F %.6F %.6F %.6F y
- h %s
- ]] ]
+ local f_radtangle = formatters[
+ [[%.6F w %.6F %.6F m
+%.6F %.6F l %.6F %.6F %.6F %.6F y
+%.6F %.6F l %.6F %.6F %.6F %.6F y
+%.6F %.6F l %.6F %.6F %.6F %.6F y
+%.6F %.6F l %.6F %.6F %.6F %.6F y
+h %s]]
+ ]
+
+ directives.register("metapost.stripzeros",function() -- confusing name but ok
+ f_rectangle = formatters["%.6N w %.6N %.6N %.6N %.6N re %s"]
+ f_baselined = formatters["%.6N w %.6N %.6N %.6N %.6N re s %.6N %.6N m %.6N %.6N l s"]
+ f_dashlined = formatters["%.6N w %.6N %.6N %.6N %.6N re s [%.6N %.6N] 2 d %.6N %.6N m %.6N %.6N l s"]
+ f_radtangle = formatters[
+[[%.6N w %.6N %.6N m
+%.6N %.6N l %.6N %.6N %.6N %.6N y
+%.6N %.6N l %.6N %.6N %.6N %.6N y
+%.6N %.6N l %.6N %.6N %.6N %.6N y
+%.6N %.6N l %.6N %.6N %.6N %.6N y
+h %s]]
+ ]
+ end)
ruleactions.fill = function(p,h,v,i,n)
local l = (p.line or 65536)*bpfactor
@@ -210,17 +238,44 @@ interfaces.implement {
local ma = getattribute(a_colormodel) or 1
local ca = getattribute(a_color)
local ta = getattribute(a_transparency)
- setfield(rule,"attr",current_attr())
+ setattrlist(rule,true)
if t.type == "mp" then
t.ma = ma
t.ca = ca
t.ta = ta
else
- rule[a_colormodel] = ma
- rule[a_color] = ca
- rule[a_transparency] = ta
+ setattr(rule,a_colormodel,ma)
+ setattr(rule,a_color,ca)
+ setattr(rule,a_transparency,ta)
end
- context(rule)
+ context(tonode(rule)) -- will become context.nodes.flush
+ end
+}
+
+interfaces.implement {
+ name = "outlinerule",
+ public = true,
+ protected = true,
+ arguments = { {
+ { "width", "dimension" },
+ { "height", "dimension" },
+ { "depth", "dimension" },
+ { "line", "dimension" },
+ } } ,
+ actions = function(t)
+ local rule = outlinerule(t.width,t.height,t.depth,t.line)
+ setattrlist(rule,true)
+ context(tonode(rule)) -- will become context.nodes.flush
+ end
+}
+
+interfaces.implement {
+ name = "framedoutline",
+ arguments = { "dimension", "dimension", "dimension", "dimension" },
+ actions = function(w,h,d,l)
+ local rule = outlinerule(w,h,d,l)
+ setattrlist(rule,true)
+ context(tonode(rule)) -- will become context.nodes.flush
end
}
@@ -247,8 +302,8 @@ interfaces.implement {
type = "mp",
name = t.name,
}
- setfield(rule,"attr",current_attr())
- context(rule)
+ setattrlist(rule,true)
+ context(tonode(rule))
end
}
diff --git a/tex/context/base/mkiv/grph-swf.lua b/tex/context/base/mkiv/grph-swf.lua
index 30089cdc4..a9297d48d 100644
--- a/tex/context/base/mkiv/grph-swf.lua
+++ b/tex/context/base/mkiv/grph-swf.lua
@@ -37,9 +37,10 @@ local function getheader(name)
buffer = f:read(20) -- ('*a')
end
f:close()
+ -- can be done better now that we have stream readers
buffer = { match(buffer,"(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)") }
for i=1,9 do
- buffer[i] = tobitstring(byte(buffer[i]))
+ buffer[i] = tobitstring(byte(buffer[i]),8,8)
end
local framebits = concat(buffer,"",1,9)
local n = tonumber(sub(framebits,1,5),2)
diff --git a/tex/context/base/mkiv/grph-trf.mkiv b/tex/context/base/mkiv/grph-trf.mkiv
index 6bd0e65cc..35e812b3e 100644
--- a/tex/context/base/mkiv/grph-trf.mkiv
+++ b/tex/context/base/mkiv/grph-trf.mkiv
@@ -146,10 +146,10 @@
\d_grph_scale_ht\ht\nextbox
\d_grph_scale_dp\dp\nextbox
%
- \global\let\finalscaleboxxscale \!!plusone
- \global\let\finalscaleboxyscale \!!plusone
- \xdef \finalscaleboxwidth {\the\d_grph_scale_wd}%
- \xdef \finalscaleboxheight{\the\d_grph_scale_ht}%
+ \glet\finalscaleboxxscale \!!plusone
+ \glet\finalscaleboxyscale \!!plusone
+ \xdef\finalscaleboxwidth {\the\d_grph_scale_wd}%
+ \xdef\finalscaleboxheight{\the\d_grph_scale_ht}%
%
\forgetall
\dontcomplain
@@ -164,11 +164,38 @@
\box\nextbox
\egroup}
+% \def\grph_scale_apply
+% {\d_grph_scale_wd\finalscaleboxxscale\d_grph_scale_wd
+% \d_grph_scale_ht\finalscaleboxyscale\d_grph_scale_ht
+% \d_grph_scale_dp\finalscaleboxyscale\d_grph_scale_dp
+% \setbox\nextbox\hpack
+% {\dostartscaling \finalscaleboxxscale \finalscaleboxyscale
+% \smashedbox\nextbox
+% \dostopscaling}%
+% \wd\nextbox\d_grph_scale_wd
+% \ht\nextbox\d_grph_scale_ht
+% \dp\nextbox\d_grph_scale_dp}
+
\def\grph_scale_apply
{\d_grph_scale_wd\finalscaleboxxscale\d_grph_scale_wd
\d_grph_scale_ht\finalscaleboxyscale\d_grph_scale_ht
\d_grph_scale_dp\finalscaleboxyscale\d_grph_scale_dp
- \setbox\nextbox\hpack
+ \ifdim\d_grph_scale_wd=\wd\nextbox
+ \ifdim\d_grph_scale_ht=\ht\nextbox
+ \ifdim\d_grph_scale_dp=\dp\nextbox
+ % \grph_scale_apply_nop
+ \else
+ \grph_scale_apply_yes
+ \fi
+ \else
+ \grph_scale_apply_yes
+ \fi
+ \else
+ \grph_scale_apply_yes
+ \fi}
+
+\def\grph_scale_apply_yes
+ {\setbox\nextbox\hpack
{\dostartscaling \finalscaleboxxscale \finalscaleboxyscale
\smashedbox\nextbox
\dostopscaling}%
@@ -871,7 +898,7 @@
\egroup}
\def\grph_rotate_finish_indeed
- {\hbox\bgroup
+ {\hpack\bgroup
\ifx\p_rotation_rotation\empty
\grph_rotate_finish_nop
\else
diff --git a/tex/context/base/mkiv/java-imp-exa.mkiv b/tex/context/base/mkiv/java-imp-example.mkiv
index 584ee1351..82d5b0cb0 100644
--- a/tex/context/base/mkiv/java-imp-exa.mkiv
+++ b/tex/context/base/mkiv/java-imp-example.mkiv
@@ -1,5 +1,5 @@
%D \module
-%D [ file=java-exa,
+%D [ file=java-imp-example, % was: java-exa
%D version=2002.??.??,
%D title=\CONTEXT\ JavaScript Macros,
%D subtitle=Example Support,
@@ -11,6 +11,9 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+%D This code is just kept as an example of dealign with forms and submitting data to
+%D a server. We used this to create stepwise growing student test forms and such.
+
% XFDF versus HTML
% localhost versus remote versus set
diff --git a/tex/context/base/mkiv/java-imp-fld.mkiv b/tex/context/base/mkiv/java-imp-fields.mkiv
index cbd53fffb..5801c3216 100644
--- a/tex/context/base/mkiv/java-imp-fld.mkiv
+++ b/tex/context/base/mkiv/java-imp-fields.mkiv
@@ -1,5 +1,5 @@
%D \module
-%D [ file=java-fld,
+%D [ file=java-imp-fields, % was java-fld
%D version=1998.05.20,
%D title=\CONTEXT\ JavaScript Macros,
%D subtitle=Field Support,
@@ -26,9 +26,9 @@
%D Probably a \UNICODE\ issue. Beware, in \MKIV\ we have a
%D different escaping of \type {\\}.
%D
-%D Watch out: cf. the latest pdf specification we've changed
-%D On into Yes. Also, we've changed the test for the on value
-%D into !Off as we dón't know what value it gets in the reader.
+%D Watch out: cf. the latest pdf specification we've changed On into Yes. Also,
+%D we've changed the test for the on value into !Off as we dón't know what value it
+%D gets in the reader.
% Is this still okay? We can have unicode now, can't we? Anyway it's kind of
% messy and unneeded in these unicode times.
@@ -262,9 +262,28 @@ function Forget_Changes() {
function ForgetChanges() {
this.dirty = false ;
}
+
+function Step_Fields (Name, First, Last) {
+ for (var i = Number(First) ; i <= Number(Last) ; i++) {
+ var s = Name + ":" + i ;
+ var v = this.getField(s) ;
+ if (v) {
+ ++visible_fields ;
+ visible_field[visible_fields] = s ;
+ if (v.hidden) {
+ v.hidden = false ;
+ this.dirty = false ;
+ return ;
+ }
+ }
+ }
+}
\stopJSpreamble
+\definereference[VideFields] [JS(Vide_Fields)]
+\definereference[HideFields] [JS(Hide_Fields)]
\definereference[ForgetChanges][JS(Forget_Changes)]
+\definereference[StepFields] [JS(Step_Fields)]
% This can be done more efficient, by keeping track of the
% current top of the stack.
@@ -278,7 +297,7 @@ function Field_Name(FieldSet,i) {
function Reset_Fields(FieldSet) {
var i = 1 ;
while (true) {
- v = Field_Name(FieldSet,i) ;
+ var v = Field_Name(FieldSet,i) ;
if (!v) {
break ;
} else {
@@ -292,7 +311,7 @@ function Reset_Fields(FieldSet) {
function Set_Fields(FieldSet) {
var i = 1 ;
while (true) {
- v = Field_Name(FieldSet,i) ;
+ var v = Field_Name(FieldSet,i) ;
if (!v) {
break ;
} else {
@@ -305,7 +324,7 @@ function Set_Fields(FieldSet) {
function Set_Field(FieldSet, FieldName) {
Reset_Fields(FieldSet) ;
- v = Field_Name(FieldSet,FieldName) ;
+ var v = Field_Name(FieldSet,FieldName) ;
if (v) {
v.value = "Yes" ;
this.dirty = false ;
@@ -314,7 +333,7 @@ function Set_Field(FieldSet, FieldName) {
function Reset_Field(FieldSet, FieldName) {
Set_Fields(FieldSet) ;
- v = Field_Name(FieldSet,FieldName) ;
+ var v = Field_Name(FieldSet,FieldName) ;
if (v) {
v.value = "Off" ;
this.dirty = false ;
@@ -323,16 +342,16 @@ function Reset_Field(FieldSet, FieldName) {
function Walk_Field(FieldSet) {
var i = 1 ;
+ this.syncAnnotScan();
while (true) {
- v = Field_Name(FieldSet,i) ;
+ var v = Field_Name(FieldSet,i) ;
if (v) {
if (v.value != "Off") {
v.value = "Off" ;
- var ii = i ;
- ii++ ;
- v = Field_Name(FieldSet,ii) ;
+ v = Field_Name(FieldSet,i + 1) ;
if (! v) {
v = Field_Name(FieldSet,1) ;
+ } else {
}
if (v) {
v.value = "Yes" ;
@@ -341,6 +360,10 @@ function Walk_Field(FieldSet) {
}
i++ ;
} else {
+ v = Field_Name(FieldSet,1) ;
+ if (v) {
+ v.value = "Yes" ;
+ }
break ;
}
}
diff --git a/tex/context/base/mkiv/java-imp-rhh.mkiv b/tex/context/base/mkiv/java-imp-highlight.mkiv
index 5f057f550..b55628f4b 100644
--- a/tex/context/base/mkiv/java-imp-rhh.mkiv
+++ b/tex/context/base/mkiv/java-imp-highlight.mkiv
@@ -1,5 +1,5 @@
%D \module
-%D [ file=java-rhh,
+%D [ file=java-imp-highlightm, % was: java-rhh
%D version=2010.02.01,
%D title=\CONTEXT\ JavaScript Macros,
%D subtitle=Runtime Highlight Hack,
diff --git a/tex/context/base/mkiv/java-imp-fil.mkiv b/tex/context/base/mkiv/java-imp-print.mkiv
index 808950f28..3d5325ff0 100644
--- a/tex/context/base/mkiv/java-imp-fil.mkiv
+++ b/tex/context/base/mkiv/java-imp-print.mkiv
@@ -1,5 +1,5 @@
%D \module
-%D [ file=java-fil,
+%D [ file=java-imp-print, % was: java-fil
%D version=1998.06.01,
%D title=\CONTEXT\ JavaScript Macros,
%D subtitle=Filing and Printing,
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\startJSpreamble Auxiliary used now
+\startJSpreamble auxiliary used now
function DocumentFileName() {
var Paths = this.path.split("/") ;
diff --git a/tex/context/base/mkiv/java-imp-stp.mkiv b/tex/context/base/mkiv/java-imp-steps.mkiv
index 8ac5d58b8..3990e4d7a 100644
--- a/tex/context/base/mkiv/java-imp-stp.mkiv
+++ b/tex/context/base/mkiv/java-imp-steps.mkiv
@@ -1,5 +1,5 @@
%D \module
-%D [ file=java-stp,
+%D [ file=java-imp-steps, % was: java-stp
%D version=2004.03.15,
%D title=\CONTEXT\ JavaScript Macros,
%D subtitle=Stepping,
diff --git a/tex/context/base/mkiv/java-imp-videoplayer.mkiv b/tex/context/base/mkiv/java-imp-videoplayer.mkiv
new file mode 100644
index 000000000..beda499a7
--- /dev/null
+++ b/tex/context/base/mkiv/java-imp-videoplayer.mkiv
@@ -0,0 +1,82 @@
+%D \module
+%D [ file=java-imp-videoplayer,
+%D version=2009.12.31,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Shockwave Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D As part of the interaction manual writing this code was moved here. It's
+%D kind of obsolete as shockwave is obsolete.
+
+% using videoplayer.swf from adobe or strobemediaplayback.swf from sourceforge:
+
+\startluaparameterset[shockwave:display]
+ toolbar = true,
+ -- preview = "somefile",
+ open = "click",
+ close = "focus",
+\stopluaparameterset
+
+\startJSpreamble shockwave used now
+
+ function StartShockwave(label) {
+ var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
+ if (rm.activated) {
+ rm.callAS("multimedia_play") ;
+ } else {
+ rm.activated = true ;
+ }
+ }
+
+ function StopShockwave(label) {
+ var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
+ if (rm.activated) {
+ rm.callAS("multimedia_pause") ;
+ rm.callAS("multimedia_rewind") ;
+ }
+ }
+
+ function RewindShockwave(label) {
+ var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
+ if (rm.activated) {
+ rm.callAS("multimedia_rewind") ;
+ }
+ }
+
+ function PauseShockwave(label) {
+ var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
+ if (rm.activated) {
+ rm.callAS("multimedia_pause") ;
+ }
+ }
+
+\stopJSpreamble
+
+\definereference[StartShockwave] [JS(StartShockwave)]
+\definereference[StopShockwave] [JS(StopShockwave)]
+\definereference[RewindShockwave][JS(RewindShockwave)]
+\definereference[PauseShockwave] [JS(PauseShockwave)]
+
+\unprotect
+
+\doglobal \useexternalfigure
+ [shockwave]
+ [videoplayer.swf]
+ [\c!arguments=\luaparameterset{shockwave:arguments}{source="\externalfigureparameter\v!file"},
+ \c!resources=\luaparameterset{shockwave:resources}{files={"\externalfigureparameter\v!file"}},
+ \c!display=shockwave:display]
+
+% \doglobal \useexternalfigure
+% [shockwave]
+% [strobemediaplayback.swf]
+% [arguments=\luaparameterset{shockwave:arguments}{src="\externalfigureparameter\v!file"},
+% resources=\luaparameterset{shockwave:resources}{files={"\externalfigureparameter\v!file"}},
+% display=shockwave:display]
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/java-imp-vplayer.mkiv b/tex/context/base/mkiv/java-imp-vplayer.mkiv
new file mode 100644
index 000000000..4ed08cad6
--- /dev/null
+++ b/tex/context/base/mkiv/java-imp-vplayer.mkiv
@@ -0,0 +1,105 @@
+%D \module
+%D [ file=java-imp-vplayer,
+%D version=2009.12.31,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Shockwave Support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+%D As part of the interaction manual writing this code was moved here. It's
+%D kind of obsolete as shockwave is obsolete. Anywaym, here's how it works.
+%D One can actually set all kind of properties but let's not waste time on
+%D that. Maybe some day \PDF\ will have proper native video support.
+%D
+%D \starttyping
+%D \starttext
+%D
+%D \useJSscripts[vplayer]
+%D
+%D \setupinteraction
+%D [state=start]
+%D
+%D \externalfigure
+%D [shockwave]
+%D [frame=on,
+%D width=480pt,
+%D height=270pt,
+%D %file=mathematics.mp4, % Hollie McNish, Martin Pyper & Jules Buckley (Metropole Orchestra)
+%D file=bathtub.mp4, % Jacob Collier & Becca Stevens
+%D label=foo]
+%D
+%D \goto{START} [JS(StartShockwave{foo})]
+%D \goto{REWIND}[JS(RewindShockwave{foo})]
+%D \goto{PAUSE} [JS(PauseShockwave{foo})]
+%D \goto{STOP} [JS(StopShockwave{foo})]
+%D
+%D \stoptext
+%D \stoptyping
+
+% using vplayer9.swf from ctan:
+
+\startluaparameterset[shockwave:display]
+ toolbar = true,
+ -- preview = "somefile",
+ open = "click",
+ close = "focus",
+\stopluaparameterset
+
+\startJSpreamble shockwave used now
+
+ function StartShockwave(label) {
+ var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
+ if (rm.activated) {
+ // ok
+ } else {
+ rm.activated = true ;
+ }
+ rm.callAS("rewind") ;
+ rm.callAS("playPause") ;
+ }
+
+ function StopShockwave(label) {
+ var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
+ if (rm.activated) {
+ rm.callAS("pause") ;
+ rm.callAS("rewind") ;
+ }
+ }
+
+ function RewindShockwave(label) {
+ var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
+ if (rm.activated) {
+ rm.callAS("rewind") ;
+ }
+ }
+
+ function PauseShockwave(label) {
+ var rm = this.getAnnotsRichMedia(this.pageNum,label)[0] ;
+ if (rm.activated) {
+ rm.callAS("playPause") ;
+ }
+ }
+
+\stopJSpreamble
+
+\definereference[StartShockwave] [JS(StartShockwave)]
+\definereference[StopShockwave] [JS(StopShockwave)]
+\definereference[RewindShockwave][JS(RewindShockwave)]
+\definereference[PauseShockwave] [JS(PauseShockwave)]
+
+\unprotect
+
+\doglobal \useexternalfigure
+ [shockwave]
+ [vplayer9.swf]
+ %[arguments=\luaparameterset{shockwave:arguments}{src="\externalfigureparameter\v!file",source="\externalfigureparameter\v!file"},
+ [\c!arguments=\luaparameterset{shockwave:arguments}{source="\externalfigureparameter\v!file",autoPlay=true},
+ \c!resources=\luaparameterset{shockwave:resources}{files={"\externalfigureparameter\v!file"}},
+ \c!display=shockwave:display]
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/java-ini.lua b/tex/context/base/mkiv/java-ini.lua
index 61ab15e7a..b41b065e8 100644
--- a/tex/context/base/mkiv/java-ini.lua
+++ b/tex/context/base/mkiv/java-ini.lua
@@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['java-ini'] = {
-- todo: don't flush scripts if no JS key
-local format = string.format
+local format, gsub, find = string.format, string.gsub, string.find
local concat = table.concat
local lpegmatch, P, S, C, Carg, Cc = lpeg.match, lpeg.P, lpeg.S, lpeg.C, lpeg.Carg, lpeg.Cc
@@ -69,6 +69,7 @@ local parsefunctions = (fname + any)^0
function javascripts.storecode(str)
local name, uses, script = lpegmatch(parsecode,str)
if name and name ~= "" then
+ script = gsub(script,"%s*([^\n\r]+)%s*[\n\r]+$","%1")
codes[name] = { uses, script }
end
end
@@ -123,8 +124,9 @@ function javascripts.usepreamblenow(name) -- now later
local names = settings_to_array(name)
for i=1,#names do
local somename = names[i]
- if not preambled[somename] then
- preambles[preambled[somename]][2] = "now"
+ local preamble = preambled[somename]
+ if preamble then
+ preambles[preamble][2] = "now"
if trace_javascript then
report_javascripts("used preamble %a, state %a, order %a",somename,"now","auto")
end
diff --git a/tex/context/base/mkiv/java-ini.mkiv b/tex/context/base/mkiv/java-ini.mkiv
index 25b8ba600..95c9c5220 100644
--- a/tex/context/base/mkiv/java-ini.mkiv
+++ b/tex/context/base/mkiv/java-ini.mkiv
@@ -38,7 +38,6 @@
%D \goto{calculate total}[Sum(1.5,2.3)]
%D \stoptyping
-
%D \macros
%D {startJScode}
%D
@@ -55,7 +54,7 @@
%D actually include the preamble needed.
%D
%D \starttyping
-%D \startJScode{uses} uses {later}
+%D \startJScode{uses} used {later}
%D uses = 6 ;
%D \stopJScode
%D \stoptyping
@@ -156,4 +155,18 @@
{\clf_usejavascriptscripts {#1}% two steps as this one calls tex code
\clf_usejavascriptpreamble{#2}}% so this one comes later
+\unexpanded\def\useJSpreamble
+ {\dosingleempty\java_use_preamble}
+
+\def\java_use_preamble[#1]%
+ {\clf_usejavascriptpreamble{#1}}% so this one comes later
+
+%D Here:
+
+\definefilesynonym[java-imp-fld.mkiv] [java-imp-fields.mkiv]
+\definefilesynonym[java-imp-stp.mkiv] [java-imp-steps.mkiv]
+\definefilesynonym[java-imp-fil.mkiv] [java-imp-print.mkiv]
+\definefilesynonym[java-imp-rhh.mkiv] [java-imp-highlight.mkiv]
+\definefilesynonym[java-imp-exa.mkiv] [java-imp-example.mkiv]
+
\protect \endinput
diff --git a/tex/context/base/mkiv/l-bit32.lua b/tex/context/base/mkiv/l-bit32.lua
index 5f35b8fee..25716e0a8 100644
--- a/tex/context/base/mkiv/l-bit32.lua
+++ b/tex/context/base/mkiv/l-bit32.lua
@@ -20,7 +20,7 @@ elseif utf8 then
-- lua 5.3: bitwise.lua, v 1.24 2014/12/26 17:20:53 roberto
- bit32 = load ( [[
+ load ( [[
local select = select -- instead of: arg = { ... }
bit32 = {
@@ -105,13 +105,13 @@ bit32 = {
return ((a & ~(mask << f)) | ((v & mask) << f)) & 0xFFFFFFFF
end,
}
- ]] )
+ ]] ) ()
elseif bit then
-- luajit (for now)
- bit32 = load ( [[
+ load ( [[
local band, bnot, rshift, lshift = bit.band, bit.bnot, bit.rshift, bit.lshift
bit32 = {
@@ -135,7 +135,7 @@ bit32 = {
rrotate = bit.ror,
rshift = rshift,
}
- ]] )
+ ]] ) ()
else
@@ -146,5 +146,3 @@ else
xpcall(function() local _, t = require("bit32") if t then bit32 = t end return end,function() end)
end
-
-return bit32 or false
diff --git a/tex/context/base/mkiv/l-dir.lua b/tex/context/base/mkiv/l-dir.lua
index bc691d536..b0b2c5283 100644
--- a/tex/context/base/mkiv/l-dir.lua
+++ b/tex/context/base/mkiv/l-dir.lua
@@ -75,7 +75,8 @@ function dir.current()
return (gsub(currentdir(),"\\","/"))
end
--- somewhat optimized
+-- The next one is somewhat optimized but still slow but it's a pitty that the iterator
+-- doesn't return a mode too.
local function glob_pattern_function(path,patt,recurse,action)
if isdir(path) then
@@ -89,6 +90,7 @@ local function glob_pattern_function(path,patt,recurse,action)
usedpath = path
end
local dirs
+ local nofdirs = 0
for name in walkdir(usedpath) do
if name ~= "." and name ~= ".." then
local full = path .. name
@@ -98,16 +100,18 @@ local function glob_pattern_function(path,patt,recurse,action)
action(full)
end
elseif recurse and mode == "directory" then
- if not dirs then
- dirs = { full }
+ if dirs then
+ nofdirs = nofdirs + 1
+ dirs[nofdirs] = full
else
- dirs[#dirs+1] = full
+ nofdirs = 1
+ dirs = { full }
end
end
end
end
if dirs then
- for i=1,#dirs do
+ for i=1,nofdirs do
glob_pattern_function(dirs[i],patt,recurse,action)
end
end
@@ -118,38 +122,41 @@ local function glob_pattern_table(path,patt,recurse,result)
if not result then
result = { }
end
- if isdir(path) then
- local usedpath
- if path == "/" then
- usedpath = "/."
- elseif not find(path,"/$") then
- usedpath = path .. "/."
- path = path .. "/"
- else
- usedpath = path
- end
- local dirs
- for name in walkdir(usedpath) do
- if name ~= "." and name ~= ".." then
- local full = path .. name
- local mode = attributes(full,'mode')
- if mode == 'file' then
- if not patt or find(full,patt) then
- result[#result+1] = full
- end
- elseif recurse and mode == "directory" then
- if not dirs then
- dirs = { full }
- else
- dirs[#dirs+1] = full
- end
+ local usedpath
+ if path == "/" then
+ usedpath = "/."
+ elseif not find(path,"/$") then
+ usedpath = path .. "/."
+ path = path .. "/"
+ else
+ usedpath = path
+ end
+ local dirs
+ local nofdirs = 0
+ local noffiles = #result
+ for name, a in walkdir(usedpath) do
+ if name ~= "." and name ~= ".." then
+ local full = path .. name
+ local mode = attributes(full,'mode')
+ if mode == 'file' then
+ if not patt or find(full,patt) then
+ noffiles = noffiles + 1
+ result[noffiles] = full
+ end
+ elseif recurse and mode == "directory" then
+ if dirs then
+ nofdirs = nofdirs + 1
+ dirs[nofdirs] = full
+ else
+ nofdirs = 1
+ dirs = { full }
end
end
end
- if dirs then
- for i=1,#dirs do
- glob_pattern_table(dirs[i],patt,recurse,result)
- end
+ end
+ if dirs then
+ for i=1,nofdirs do
+ glob_pattern_table(dirs[i],patt,recurse,result)
end
end
return result
@@ -160,12 +167,13 @@ local function globpattern(path,patt,recurse,method)
if patt and sub(patt,1,-3) == path then
patt = false
end
+ local okay = isdir(path)
if kind == "function" then
- return glob_pattern_function(path,patt,recurse,method)
+ return okay and glob_pattern_function(path,patt,recurse,method) or { }
elseif kind == "table" then
- return glob_pattern_table(path,patt,recurse,method)
+ return okay and glob_pattern_table(path,patt,recurse,method) or method
else
- return glob_pattern_table(path,patt,recurse,{ })
+ return okay and glob_pattern_table(path,patt,recurse,{ }) or { }
end
end
diff --git a/tex/context/base/mkiv/l-file.lua b/tex/context/base/mkiv/l-file.lua
index 5fec0040f..46b6847d3 100644
--- a/tex/context/base/mkiv/l-file.lua
+++ b/tex/context/base/mkiv/l-file.lua
@@ -69,35 +69,34 @@ local lpegmatch = lpeg.match
local getcurrentdir, attributes = lfs.currentdir, lfs.attributes
local checkedsplit = string.checkedsplit
--- local patterns = file.patterns or { }
--- file.patterns = patterns
-
local P, R, S, C, Cs, Cp, Cc, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc, lpeg.Ct
-- better this way:
-local tricky = S("/\\") * P(-1)
+----- tricky = S("/\\") * P(-1)
local attributes = lfs.attributes
-if sandbox then
- sandbox.redefine(lfs.isfile,"lfs.isfile")
- sandbox.redefine(lfs.isdir, "lfs.isdir")
-end
-
function lfs.isdir(name)
- if lpegmatch(tricky,name) then
- return attributes(name,"mode") == "directory"
- else
- return attributes(name.."/.","mode") == "directory"
- end
+ -- if not lpegmatch(tricky,name) then
+ -- name = name .. "/."
+ -- end
+ return attributes(name,"mode") == "directory"
end
function lfs.isfile(name)
- return attributes(name,"mode") == "file"
+ local a = attributes(name,"mode")
+ return a == "file" or a == "link" or nil
end
function lfs.isfound(name)
- return attributes(name,"mode") == "file" and name or nil
+ local a = attributes(name,"mode")
+ return (a == "file" or a == "link") and name or nil
+end
+
+if sandbox then
+ sandbox.redefine(lfs.isfile,"lfs.isfile")
+ sandbox.redefine(lfs.isdir, "lfs.isdir")
+ sandbox.redefine(lfs.isfound, "lfs.isfound")
end
local colon = P(":")
@@ -725,3 +724,10 @@ function file.withinbase(path) -- don't go beyond root
return true
end
+-- not used in context but was in luatex once:
+
+local symlinkattributes = lfs.symlinkattributes
+
+function lfs.readlink(name)
+ return symlinkattributes(name,"target") or nil
+end
diff --git a/tex/context/base/mkiv/l-lpeg.lua b/tex/context/base/mkiv/l-lpeg.lua
index a7ebd567d..51bc1d3df 100644
--- a/tex/context/base/mkiv/l-lpeg.lua
+++ b/tex/context/base/mkiv/l-lpeg.lua
@@ -202,13 +202,13 @@ local fullstripper = whitespace^0 * C((whitespace^0 * nonwhitespace^1)^0)
local collapser = Cs(spacer^0/"" * nonspacer^0 * ((spacer^0/" " * nonspacer^1)^0))
local nospacer = Cs((whitespace^1/"" + nonwhitespace^1)^0)
-local b_collapser = Cs( whitespace^0 /"" * (nonwhitespace^1 + whitespace^1/" ")^0)
-local e_collapser = Cs((whitespace^1 * P(-1)/"" + nonwhitespace^1 + whitespace^1/" ")^0)
-local m_collapser = Cs( (nonwhitespace^1 + whitespace^1/" ")^0)
+local b_collapser = Cs( whitespace^0 /"" * (nonwhitespace^1 + whitespace^1/" ")^0)
+local e_collapser = Cs((whitespace^1 * endofstring/"" + nonwhitespace^1 + whitespace^1/" ")^0)
+local m_collapser = Cs( (nonwhitespace^1 + whitespace^1/" ")^0)
-local b_stripper = Cs( spacer^0 /"" * (nonspacer^1 + spacer^1/" ")^0)
-local e_stripper = Cs((spacer^1 * P(-1)/"" + nonspacer^1 + spacer^1/" ")^0)
-local m_stripper = Cs( (nonspacer^1 + spacer^1/" ")^0)
+local b_stripper = Cs( spacer^0 /"" * (nonspacer^1 + spacer^1/" ")^0)
+local e_stripper = Cs((spacer^1 * endofstring/"" + nonspacer^1 + spacer^1/" ")^0)
+local m_stripper = Cs( (nonspacer^1 + spacer^1/" ")^0)
patterns.stripper = stripper
patterns.fullstripper = fullstripper
@@ -270,7 +270,7 @@ patterns.cpfloat = sign^-1 * patterns.cpunsigned
patterns.number = patterns.float + patterns.integer
patterns.cnumber = patterns.cfloat + patterns.integer
patterns.cpnumber = patterns.cpfloat + patterns.integer
-patterns.oct = zero * octdigits
+patterns.oct = zero * octdigits -- hm is this ok
patterns.octal = patterns.oct
patterns.HEX = zero * P("X") * (digit+uppercase)^1
patterns.hex = zero * P("x") * (digit+lowercase)^1
@@ -289,10 +289,14 @@ patterns.propername = (uppercase + lowercase + underscore) * (uppercase + low
patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
patterns.beginline = #(1-newline)
-patterns.longtostring = Cs(whitespace^0/"" * ((patterns.quoted + nonwhitespace^1 + whitespace^1/"" * (P(-1) + Cc(" ")))^0))
+patterns.longtostring = Cs(whitespace^0/"" * ((patterns.quoted + nonwhitespace^1 + whitespace^1/"" * (endofstring + Cc(" ")))^0))
-local function anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) }
+-- local function anywhere(pattern) -- slightly adapted from website
+-- return P { P(pattern) + 1 * V(1) }
+-- end
+
+function anywhere(pattern) -- faster
+ return (1-P(pattern))^0 * P(pattern)
end
lpeg.anywhere = anywhere
@@ -304,12 +308,28 @@ function lpeg.instringchecker(p)
end
end
+-- function lpeg.splitter(pattern, action)
+-- return (((1-P(pattern))^1)/action+1)^0
+-- end
+
+-- function lpeg.tsplitter(pattern, action)
+-- return Ct((((1-P(pattern))^1)/action+1)^0)
+-- end
+
function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
+ if action then
+ return (((1-P(pattern))^1)/action+1)^0
+ else
+ return (Cs((1-P(pattern))^1)+1)^0
+ end
end
function lpeg.tsplitter(pattern, action)
- return Ct((((1-P(pattern))^1)/action+1)^0)
+ if action then
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+ else
+ return Ct((Cs((1-P(pattern))^1)+1)^0)
+ end
end
-- probleem: separator can be lpeg and that does not hash too well, but
@@ -637,82 +657,6 @@ function lpeg.counter(pattern,action)
end
end
--- utf extensies
-
-utf = utf or (unicode and unicode.utf8) or { }
-
-local utfcharacters = utf and utf.characters or string.utfcharacters
-local utfgmatch = utf and utf.gmatch
-local utfchar = utf and utf.char
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p = P(false)
- for uc in utfcharacters(str) do
- p = p + P(uc)
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p = P(false)
- for uc in utfgmatch(str,".") do
- p = p + P(uc)
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p = P(false)
- local f = function(uc)
- p = p + P(uc)
- end
- lpegmatch((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = utf8byte * utf8byte + Cc(false) -- utf8byte is already a capture
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = lpegmatch(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and (last - first < 8) then -- a somewhat arbitrary criterium
- local p = P(false)
- for i=first,last do
- p = p + P(utfchar(i))
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- -- tricky, these nested captures
- return utf8byte / f -- nil when invalid range
- end
-end
-
--- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω"))
-
-- lpeg.print(lpeg.R("ab","cd","gh"))
-- lpeg.print(lpeg.P("a","b","c"))
-- lpeg.print(lpeg.S("a","b","c"))
@@ -944,7 +888,7 @@ local function make2(t,rest) -- only ascii
return p
end
-function lpeg.utfchartabletopattern(list,insensitive) -- goes to util-lpg
+local function utfchartabletopattern(list,insensitive) -- goes to util-lpg
local tree = { }
local n = #list
if n == 0 then
@@ -1022,6 +966,15 @@ function lpeg.utfchartabletopattern(list,insensitive) -- goes to util-lpg
return (insensitive and make2 or make1)(tree)
end
+lpeg.utfchartabletopattern = utfchartabletopattern
+
+function lpeg.utfreplacer(list,insensitive)
+ local pattern = Cs((utfchartabletopattern(list,insensitive)/list + utf8character)^0)
+ return function(str)
+ return lpegmatch(pattern,str) or str
+ end
+end
+
-- local t = { "start", "stoep", "staart", "paard" }
-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1)
@@ -1119,25 +1072,38 @@ end
-- moved here (before util-str)
------ digit = R("09")
------ period = P(".")
------ zero = P("0")
-local trailingzeros = zero^0 * -digit -- suggested by Roberto R
-local case_1 = period * trailingzeros / ""
-local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "")
-local number = digits * (case_1 + case_2)
-local stripper = Cs((number + 1)^0)
+do
+
+ local trailingzeros = zero^0 * -digit -- suggested by Roberto
+ local stripper = Cs((
+ digits * (
+ period * trailingzeros / ""
+ + period * (digit - trailingzeros)^1 * (trailingzeros / "")
+ ) + 1
+ )^0)
-lpeg.patterns.stripzeros = stripper
+ lpeg.patterns.stripzeros = stripper -- multiple in string
--- local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100"
--- collectgarbage("collect")
--- str = string.rep(sample,10000)
--- local ts = os.clock()
--- lpegmatch(stripper,str)
--- print(#str, os.clock()-ts, lpegmatch(stripper,sample))
+ local nonzero = digit - zero
+ local trailingzeros = zero^1 * endofstring
+ local stripper = Cs( (1-period)^0 * (
+ period * trailingzeros/""
+ + period * (nonzero^1 + (trailingzeros/"") + zero^1)^0
+ + endofstring
+ ))
+
+ lpeg.patterns.stripzero = stripper -- slightly more efficient but expects a float !
+
+ -- local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100"
+ -- collectgarbage("collect")
+ -- str = string.rep(sample,10000)
+ -- local ts = os.clock()
+ -- lpegmatch(stripper,str)
+ -- print(#str, os.clock()-ts, lpegmatch(stripper,sample))
+
+end
--- for practical reasone we keep this here:
+-- for practical reasons we keep this here:
local byte_to_HEX = { }
local byte_to_hex = { }
@@ -1209,3 +1175,22 @@ end
-- local h = "ADFE0345"
-- local b = lpegmatch(patterns.hextobytes,h)
-- print(h,b,string.tohex(b),string.toHEX(b))
+
+local patterns = { } -- can be made weak
+
+local function containsws(what)
+ local p = patterns[what]
+ if not p then
+ local p1 = P(what) * (whitespace + endofstring) * Cc(true)
+ local p2 = whitespace * P(p1)
+ p = P(p1) + P(1-p2)^0 * p2 + Cc(false)
+ patterns[what] = p
+ end
+ return p
+end
+
+lpeg.containsws = containsws
+
+function string.containsws(str,what)
+ return lpegmatch(patterns[what] or containsws(what),str)
+end
diff --git a/tex/context/base/mkiv/l-lua.lua b/tex/context/base/mkiv/l-lua.lua
index 426706f06..d8989364e 100644
--- a/tex/context/base/mkiv/l-lua.lua
+++ b/tex/context/base/mkiv/l-lua.lua
@@ -35,8 +35,6 @@ if LUAVERSION < 5.2 and jit then
LUAVERSION = 5.2
end
-_LUAVERSION = LUAVERSION -- for old times sake, will go away
-
-- lpeg
if not lpeg then
@@ -230,23 +228,27 @@ elseif not ffi.number then
ffi.number = tonumber
end
-if not bit32 then -- and utf8 then
- -- bit32 = load ( [[ -- replacement code with 5.3 syntax so that 5.2 doesn't bark on it ]] )
- bit32 = require("l-bit32")
-end
+-- if not bit32 then -- and utf8 then
+-- -- bit32 = load ( [[ -- replacement code with 5.3 syntax so that 5.2 doesn't bark on it ]] )
+-- bit32 = require("l-bit32")
+-- end
-- We need this due a bug in luatex socket loading:
-local loaded = package.loaded
-
-if not loaded["socket"] then loaded["socket"] = loaded["socket.core"] end
-if not loaded["mime"] then loaded["mime"] = loaded["mime.core"] end
-
-if not socket.mime then socket.mime = package.loaded["mime"] end
-
-if not loaded["socket.mime"] then loaded["socket.mime"] = socket.mime end
-if not loaded["socket.http"] then loaded["socket.http"] = socket.http end
-if not loaded["socket.ftp"] then loaded["socket.ftp"] = socket.ftp end
-if not loaded["socket.smtp"] then loaded["socket.smtp"] = socket.smtp end
-if not loaded["socket.tp"] then loaded["socket.tp"] = socket.tp end
-if not loaded["socket.url"] then loaded["socket.url"] = socket.url end
+-- local loaded = package.loaded
+--
+-- if not loaded["socket"] then loaded["socket"] = loaded["socket.core"] end
+-- if not loaded["mime"] then loaded["mime"] = loaded["mime.core"] end
+--
+-- if not socket.mime then socket.mime = package.loaded["mime"] end
+--
+-- if not loaded["socket.mime"] then loaded["socket.mime"] = socket.mime end
+-- if not loaded["socket.http"] then loaded["socket.http"] = socket.http end
+-- if not loaded["socket.ftp"] then loaded["socket.ftp"] = socket.ftp end
+-- if not loaded["socket.smtp"] then loaded["socket.smtp"] = socket.smtp end
+-- if not loaded["socket.tp"] then loaded["socket.tp"] = socket.tp end
+-- if not loaded["socket.url"] then loaded["socket.url"] = socket.url end
+
+if LUAVERSION > 5.3 then
+ collectgarbage("generational")
+end
diff --git a/tex/context/base/mkiv/l-macro-imp-optimize.lua b/tex/context/base/mkiv/l-macro-imp-optimize.lua
index e04b37eab..7d7fafefd 100644
--- a/tex/context/base/mkiv/l-macro-imp-optimize.lua
+++ b/tex/context/base/mkiv/l-macro-imp-optimize.lua
@@ -46,17 +46,22 @@ if LUAVERSION >= 5.3 and lua.macros then
-- #define rshift(a,b) ((a >> b) & 0xFFFFFFFF)
-- ]]
- lua.macros.resolvestring [[
- #define band(a,b) (a&b)
- #define bnot(a) (~a&0xFFFFFFFF)
- #define bor(a,b) ((a|b)&0xFFFFFFFF)
- #define btest(a,b) ((a&b)~=0)
- #define bxor(a,b) ((a~b)&0xFFFFFFFF)
- #define rshift(a,b) ((a&b)~=0)
- #define extract(a,b,c) ((a>>b)&~(-1<<c))
- #define extract(a,b) ((a>>b)&0x1))
- #define lshift(a,b) ((a<<b)&0xFFFFFFFF)
- #define rshift(a,b) ((a>>b)&0xFFFFFFFF)
- ]]
+lua.macros.resolvestring [[
+#define band(a,b) ((a)&(b))
+#define bnot(a) (~(a)&0xFFFFFFFF)
+#define bor(a,b) (((a)|(b))&0xFFFFFFFF)
+#define btest(a,b) (((a)&(b))~=0)
+#define bxor(a,b) (((a)~(b))&0xFFFFFFFF)
+#define rshift(a,b) (((a)&(b))~=0)
+#define extract(a,b,c) (((a)>>(b))&~(-1<<(c)))
+#define extract(a,b) (((a)>>(b))&0x1)
+#define extract1(a,b) ((a >> b) & 0x01)
+#define extract2(a,b) ((a >> b) & 0x03)
+#define extract4(a,b) ((a >> b) & 0x0F)
+#define lshift(a,b) (((a)<<(b))&0xFFFFFFFF)
+#define rshift(a,b) (((a)>>(b))&0xFFFFFFFF)
+#define intdiv(a,b) ((a)//(b))
+#define idiv(a,b) ((a)//(b))
+]]
end
diff --git a/tex/context/base/mkiv/l-macro.lua b/tex/context/base/mkiv/l-macro.lua
index 30c7cbec6..24a3d07bc 100644
--- a/tex/context/base/mkiv/l-macro.lua
+++ b/tex/context/base/mkiv/l-macro.lua
@@ -14,14 +14,16 @@ if not modules then modules = { } end modules ['l-macros'] = {
local S, P, R, V, C, Cs, Cc, Ct, Carg = lpeg.S, lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Carg
local lpegmatch = lpeg.match
local concat = table.concat
-local format, sub = string.format, string.sub
+local format, sub, match = string.format, string.sub, string.match
local next, load, type = next, load, type
local newline = S("\n\r")^1
local continue = P("\\") * newline
+local whitespace = S(" \t\n\r")
local spaces = S(" \t") + continue
-local name = R("az","AZ","__","09")^1
-local body = ((1+continue/"")-newline)^1
+local nametoken = R("az","AZ","__","09")
+local name = nametoken^1
+local body = ((continue/"" + 1) - newline)^1
local lparent = P("(")
local rparent = P(")")
local noparent = 1 - (lparent + rparent)
@@ -53,7 +55,9 @@ end
-- todo: zero case
-resolve = C(C(name) * arguments^-1) / function(raw,s,a)
+local safeguard = P("local") * whitespace^1 * name * (whitespace + P("="))
+
+resolve = safeguard + C(C(name) * (arguments^-1)) / function(raw,s,a)
local d = definitions[s]
if d then
if a then
@@ -85,7 +89,7 @@ subparser = Cs((resolve + P(1))^1)
local enddefine = P("#enddefine") / ""
-local beginregister = (C(name) * spaces^0 * (arguments + Cc(false)) * C((1-enddefine)^1) * enddefine) / function(k,a,v)
+local beginregister = (C(name) * (arguments + Cc(false)) * C((1-enddefine)^1) * enddefine) / function(k,a,v)
local n = 0
if a then
n = #a
@@ -103,14 +107,14 @@ local beginregister = (C(name) * spaces^0 * (arguments + Cc(false)) * C((1-endde
end
local d = definitions[k]
if not d then
- d = { [0] = false, false, false, false, false, false, false, false, false }
+ d = { a = a, [0] = false, false, false, false, false, false, false, false, false }
definitions[k] = d
end
d[n] = lpegmatch(subparser,v) or v
return ""
end
-local register = (C(name) * spaces^0 * (arguments + Cc(false)) * spaces^0 * C(body)) / function(k,a,v)
+local register = (Cs(name) * (arguments + Cc(false)) * spaces^0 * Cs(body)) / function(k,a,v)
local n = 0
if a then
n = #a
@@ -128,7 +132,7 @@ local register = (C(name) * spaces^0 * (arguments + Cc(false)) * spaces^0 * C(bo
end
local d = definitions[k]
if not d then
- d = { [0] = false, false, false, false, false, false, false, false, false }
+ d = { a = a, [0] = false, false, false, false, false, false, false, false, false }
definitions[k] = d
end
d[n] = lpegmatch(subparser,v) or v
@@ -162,6 +166,25 @@ function macros.reset()
patterns = { }
end
+function macros.showdefinitions()
+ -- no helpers loaded but not called early
+ for name, list in table.sortedhash(definitions) do
+ local arguments = list.a
+ if arguments then
+ arguments = "(" .. concat(arguments,",") .. ")"
+ else
+ arguments = ""
+ end
+ print("macro: " .. name .. arguments)
+ for i=0,#list do
+ local l = list[i]
+ if l then
+ print(" " .. l)
+ end
+ end
+ end
+end
+
function macros.resolvestring(str)
return lpegmatch(parser,str) or str
end
@@ -170,6 +193,51 @@ function macros.resolving()
return next(patterns)
end
+local function reload(path,name,data)
+ local only = match(name,".-([^/]+)%.lua")
+ if only and only ~= "" then
+ local name = path .. "/" .. only
+ local f = io.open(name,"wb")
+ f:write(data)
+ f:close()
+ local f = loadfile(name)
+ os.remove(name)
+ return f
+ end
+end
+
+-- local function reload(path,name,data)
+-- if path and path ~= "" then
+-- local only = file.nameonly(name) .. "-macro.lua"
+-- local name = file.join(path,only)
+-- io.savedata(name,data)
+-- local l = loadfile(name)
+-- os.remove(name)
+-- return l
+-- end
+-- return load(data,name)
+-- end
+--
+-- assumes no helpers
+
+local function reload(path,name,data)
+ if path and path ~= "" then
+ local only = string.match(name,".-([^/]+)%.lua")
+ if only and only ~= "" then
+ local name = path .. "/" .. only .. "-macro.lua"
+ local f = io.open(name,"wb")
+ if f then
+ f:write(data)
+ f:close()
+ local l = loadfile(name)
+ os.remove(name)
+ return l
+ end
+ end
+ end
+ return load(data,name)
+end
+
local function loaded(name,trace,detail)
-- local c = io.loaddata(fullname) -- not yet available
local f = io.open(name,"rb")
@@ -194,12 +262,11 @@ local function loaded(name,trace,detail)
report_lua("no macros expanded in '%s'",name)
end
end
- if #name > 30 then
- n = "--[[" .. sub(name,-30) .. "]] " .. n
- else
- n = "--[[" .. name .. "]] " .. n
- end
- return load(n)
+ -- if #name > 30 then
+ -- name = sub(name,-30)
+ -- end
+ -- n = "--[[" .. name .. "]]\n" .. n
+ return reload(lfs and lfs.currentdir(),name,n)
end
macros.loaded = loaded
diff --git a/tex/context/base/mkiv/l-number.lua b/tex/context/base/mkiv/l-number.lua
index a83e8f8f9..9fd2f82f7 100644
--- a/tex/context/base/mkiv/l-number.lua
+++ b/tex/context/base/mkiv/l-number.lua
@@ -81,13 +81,14 @@ if bit32 then
"0", "0", "0", "0", "0", "0", "0", "0",
}
- function number.tobitstring(b,m)
- -- if really needed we can speed this one up
- -- because small numbers need less extraction
- local n = 32
- for i=0,31 do
+ function number.tobitstring(b,m,w)
+ if not w then
+ w = 32
+ end
+ local n = w
+ for i=0,w-1 do
local v = bextract(b,i)
- local k = 32 - i
+ local k = w - i
if v == 1 then
n = k
t[k] = "1"
@@ -95,12 +96,14 @@ if bit32 then
t[k] = "0"
end
end
- if m then
+ if w then
+ return concat(t,"",1,w)
+ elseif m then
m = 33 - m * 8
if m < 1 then
m = 1
end
- return concat(t,"",m)
+ return concat(t,"",1,m)
elseif n < 8 then
return concat(t)
elseif n < 16 then
@@ -232,3 +235,7 @@ function number.decimaltobyte(d)
return b
end
end
+
+function number.idiv(i,d)
+ return floor(i/d) -- i//d in 5.3
+end
diff --git a/tex/context/base/mkiv/l-os.lua b/tex/context/base/mkiv/l-os.lua
index 9b54c9840..cf469f79d 100644
--- a/tex/context/base/mkiv/l-os.lua
+++ b/tex/context/base/mkiv/l-os.lua
@@ -32,11 +32,78 @@ local concat = table.concat
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.
+-- This check needs to happen real early on. Todo: we can pick it up from the commandline
+-- if we pass --binpath= (which is useful anyway)
+
+do
+ local selfdir = os.selfdir
+ if selfdir == "" then
+ selfdir = nil
+ end
+ if not selfdir then
+ -- We need a fallback plan so let's see what we get.
+ if arg then
+ -- passed by mtx-context ... saves network access
+ for i=1,#arg do
+ local a = arg[i]
+ if find(a,"^%-%-[c:]*texmfbinpath=") then
+ selfdir = gsub(a,"^.-=","")
+ break
+ end
+ end
+ end
+ if not selfdir then
+ selfdir = os.selfbin or "luatex"
+ if find(selfdir,"[/\\]") then
+ selfdir = gsub(selfdir,"[/\\][^/\\]*$","")
+ elseif os.getenv then
+ local path = os.getenv("PATH")
+ local name = gsub(selfdir,"^.*[/\\][^/\\]","")
+ local patt = "[^:]+"
+ if os.type == "windows" then
+ patt = "[^;]+"
+ name = name .. ".exe"
+ end
+ local isfile
+ if lfs then
+ -- we're okay as lfs is assumed present
+ local attributes = lfs.attributes
+ isfile = function(name)
+ local a = attributes(name,"mode")
+ return a == "file" or a == "link" or nil
+ end
+ else
+ -- we're not okay and much will not work as we miss lfs
+ local open = io.open
+ isfile = function(name)
+ local f = open(name)
+ if f then
+ f:close()
+ return true
+ end
+ end
+ end
+ for p in gmatch(path,patt) do
+ -- possible speedup: there must be tex in 'p'
+ if isfile(p .. "/" .. name) then
+ selfdir = p
+ break
+ end
+ end
+ end
+ end
+ -- let's hope we're okay now
+ os.selfdir = selfdir or "."
+ end
+end
+-- print(os.selfdir) os.exit()
+
+-- 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.
+-- as the binary (Luatex is normally okay). But to be sure we set the seed anyway. It will be better
+-- in Lua 5.4 (according to the announcements.)
math.initialseed = tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6))
@@ -156,7 +223,7 @@ end
local launchers = {
windows = "start %s",
macosx = "open %s",
- unix = "$BROWSER %s &> /dev/null &",
+ unix = "xdg-open %s &> /dev/null &",
}
function os.launch(str)
@@ -223,6 +290,13 @@ local name, platform = os.name or "linux", os.getenv("MTX_PLATFORM") or ""
-- os.bits = 32 | 64
+-- os.uname()
+-- sysname
+-- machine
+-- release
+-- version
+-- nodename
+
if platform ~= "" then
os.platform = platform
@@ -234,10 +308,12 @@ elseif os.type == "windows" then
-- PROCESSOR_ARCHITECTURE : binary platform
-- PROCESSOR_ARCHITEW6432 : OS platform
+ -- mswin-64 is now win64
+
function resolvers.platform(t,k)
- local platform, architecture = "", os.getenv("PROCESSOR_ARCHITECTURE") or ""
+ local architecture = os.getenv("PROCESSOR_ARCHITECTURE") or ""
+ local platform = ""
if find(architecture,"AMD64",1,true) then
- -- platform = "mswin-64"
platform = "win64"
else
platform = "mswin"
@@ -251,13 +327,17 @@ elseif name == "linux" then
function resolvers.platform(t,k)
-- we sometimes have HOSTTYPE set so let's check that first
- local platform, architecture = "", os.getenv("HOSTTYPE") or resultof("uname -m") or ""
- if find(architecture,"x86_64",1,true) then
- platform = "linux-64"
+ local architecture = os.getenv("HOSTTYPE") or resultof("uname -m") or ""
+ local platform = os.getenv("MTX_PLATFORM") or ""
+ local musl = find(os.selfdir or "","linuxmusl")
+ if platform ~= "" then
+ -- we're done
+ elseif find(architecture,"x86_64",1,true) then
+ platform = musl and "linuxmusl" or "linux-64"
elseif find(architecture,"ppc",1,true) then
platform = "linux-ppc"
else
- platform = "linux"
+ platform = musl and "linuxmusl" or "linux"
end
os.setenv("MTX_PLATFORM",platform)
os.platform = platform
@@ -277,11 +357,13 @@ elseif name == "macosx" then
]]--
function resolvers.platform(t,k)
- -- local platform, architecture = "", os.getenv("HOSTTYPE") or ""
+ -- local platform = ""
+ -- local architecture = os.getenv("HOSTTYPE") or ""
-- if architecture == "" then
-- architecture = resultof("echo $HOSTTYPE") or ""
-- end
- local platform, architecture = "", resultof("echo $HOSTTYPE") or ""
+ local architecture = resultof("echo $HOSTTYPE") or ""
+ local platform = ""
if architecture == "" then
-- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n")
platform = "osx-intel"
@@ -300,7 +382,8 @@ elseif name == "macosx" then
elseif name == "sunos" then
function resolvers.platform(t,k)
- local platform, architecture = "", resultof("uname -m") or ""
+ local architecture = resultof("uname -m") or ""
+ local platform = ""
if find(architecture,"sparc",1,true) then
platform = "solaris-sparc"
else -- if architecture == 'i86pc'
@@ -314,7 +397,8 @@ elseif name == "sunos" then
elseif name == "freebsd" then
function resolvers.platform(t,k)
- local platform, architecture = "", resultof("uname -m") or ""
+ local architecture = resultof("uname -m") or ""
+ local platform = ""
if find(architecture,"amd64",1,true) then
platform = "freebsd-amd64"
else
@@ -329,7 +413,8 @@ elseif name == "kfreebsd" then
function resolvers.platform(t,k)
-- we sometimes have HOSTTYPE set so let's check that first
- local platform, architecture = "", os.getenv("HOSTTYPE") or resultof("uname -m") or ""
+ local architecture = os.getenv("HOSTTYPE") or resultof("uname -m") or ""
+ local platform = ""
if find(architecture,"x86_64",1,true) then
platform = "kfreebsd-amd64"
else
@@ -564,3 +649,20 @@ function os.validdate(year,month,day)
end
return year, month, day
end
+
+local osexit = os.exit
+local exitcode = nil
+
+function os.setexitcode(code)
+ exitcode = code
+end
+
+function os.exit(c)
+ if exitcode ~= nil then
+ return osexit(exitcode)
+ end
+ if c ~= nil then
+ return osexit(c)
+ end
+ return osexit()
+end
diff --git a/tex/context/base/mkiv/l-package.lua b/tex/context/base/mkiv/l-package.lua
index 4faee76bf..0dd71e5ec 100644
--- a/tex/context/base/mkiv/l-package.lua
+++ b/tex/context/base/mkiv/l-package.lua
@@ -394,3 +394,7 @@ end
-- front ..
table.insert(searchers,1,helpers.loaded)
+
+if context then
+ package.path = ""
+end
diff --git a/tex/context/base/mkiv/l-sandbox.lua b/tex/context/base/mkiv/l-sandbox.lua
index 2ecec0023..c2e1753d3 100644
--- a/tex/context/base/mkiv/l-sandbox.lua
+++ b/tex/context/base/mkiv/l-sandbox.lua
@@ -190,6 +190,9 @@ end
function sandbox.enable()
if not sandboxed then
+ debug = {
+ traceback = debug.traceback,
+ }
for i=1,#initializers do
initializers[i].action()
end
diff --git a/tex/context/base/mkiv/l-sha.lua b/tex/context/base/mkiv/l-sha.lua
new file mode 100644
index 000000000..8481f7f45
--- /dev/null
+++ b/tex/context/base/mkiv/l-sha.lua
@@ -0,0 +1,27 @@
+if not modules then modules = { } end modules ['l-sha'] = {
+ 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"
+}
+
+if sha2 then
+
+ local lpegmatch = lpeg.match
+ local lpegpatterns = lpeg.patterns
+ local bytestohex = lpegpatterns.bytestohex
+ local bytestoHEX = lpegpatterns.bytestoHEX
+
+ local digest256 = sha2.digest256
+ local digest384 = sha2.digest384
+ local digest512 = sha2.digest512
+
+ sha2.hash256 = function(str) return lpegmatch(bytestohex,digest256(str)) end
+ sha2.hash384 = function(str) return lpegmatch(bytestohex,digest384(str)) end
+ sha2.hash512 = function(str) return lpegmatch(bytestohex,digest512(str)) end
+ sha2.HASH256 = function(str) return lpegmatch(bytestoHEX,digest256(str)) end
+ sha2.HASH384 = function(str) return lpegmatch(bytestoHEX,digest384(str)) end
+ sha2.HASH512 = function(str) return lpegmatch(bytestoHEX,digest512(str)) end
+
+end
diff --git a/tex/context/base/mkiv/l-table.lua b/tex/context/base/mkiv/l-table.lua
index 5cd65dd67..57130a50d 100644
--- a/tex/context/base/mkiv/l-table.lua
+++ b/tex/context/base/mkiv/l-table.lua
@@ -8,10 +8,9 @@ if not modules then modules = { } end modules ['l-table'] = {
local type, next, tostring, tonumber, select = type, next, tostring, tonumber, select
local table, string = table, string
-local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
+local concat, sort = table.concat, table.sort
local format, lower, dump = string.format, string.lower, string.dump
local getmetatable, setmetatable = getmetatable, setmetatable
-local getinfo = debug.getinfo
local lpegmatch, patterns = lpeg.match, lpeg.patterns
local floor = math.floor
@@ -27,7 +26,8 @@ function table.getn(t)
end
function table.strip(tab)
- local lst, l = { }, 0
+ local lst = { }
+ local l = 0
for i=1,#tab do
local s = lpegmatch(stripper,tab[i]) or ""
if s == "" then
@@ -42,7 +42,8 @@ end
function table.keys(t)
if t then
- local keys, k = { }, 0
+ local keys = { }
+ local k = 0
for key in next, t do
k = k + 1
keys[k] = key
@@ -146,7 +147,9 @@ end
local function sortedkeys(tab)
if tab then
- local srt, category, s = { }, 0, 0 -- 0=unknown 1=string, 2=number 3=mixed
+ local srt = { }
+ local category = 0 -- 0=unknown 1=string, 2=number 3=mixed
+ local s = 0
for key in next, tab do
s = s + 1
srt[s] = key
@@ -186,7 +189,8 @@ end
local function sortedhashonly(tab)
if tab then
- local srt, s = { }, 0
+ local srt = { }
+ local s = 0
for key in next, tab do
if type(key) == "string" then
s = s + 1
@@ -204,7 +208,8 @@ end
local function sortedindexonly(tab)
if tab then
- local srt, s = { }, 0
+ local srt = { }
+ local s = 0
for key in next, tab do
if type(key) == "number" then
s = s + 1
@@ -222,7 +227,8 @@ end
local function sortedhashkeys(tab,cmp) -- fast one
if tab then
- local srt, s = { }, 0
+ local srt = { }
+ local s = 0
for key in next, tab do
if key then
s= s + 1
@@ -318,7 +324,9 @@ end
-- end
function table.merge(t, ...) -- first one is target
- t = t or { }
+ if not t then
+ t = { }
+ end
for i=1,select("#",...) do
for k, v in next, (select(i,...)) do
t[k] = v
@@ -384,7 +392,8 @@ end
-- end
function table.imerged(...)
- local tmp, ntmp = { }, 0
+ local tmp = { }
+ local ntmp = 0
for i=1,select("#",...) do
local nst = select(i,...)
for j=1,#nst do
@@ -421,7 +430,9 @@ end
-- todo : copy without metatable
local function copy(t,tables) -- taken from lua wiki, slightly adapted
- tables = tables or { }
+ if not tables then
+ tables = { }
+ end
local tcopy = { }
if not tables[t] then
tables[t] = tcopy
@@ -472,7 +483,8 @@ function table.tohash(t,value)
end
function table.fromhash(t)
- local hsh, h = { }, 0
+ local hsh = { }
+ local h = 0
for k, v in next, t do
if v then
h = h + 1
@@ -670,7 +682,8 @@ local function do_serialize(root,name,depth,level,indexed)
end
-- we could check for k (index) being number (cardinal)
if root and next(root) ~= nil then
- local first, last = nil, 0
+ local first = nil
+ local last = 0
if compact then
last = #root
for k=1,last do
@@ -830,22 +843,25 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif tv == "function" then
if functions then
- local f = getinfo(v).what == "C" and dump(dummy) or dump(v) -- maybe strip
- -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v) -- maybe strip
- if tk == "number" then
- if hexify then
- handle(format("%s [0x%X]=load(%q),",depth,k,f))
+ local getinfo = debug and debug.getinfo
+ if getinfo then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v) -- maybe strip
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v) -- maybe strip
+ if tk == "number" then
+ if hexify then
+ handle(format("%s [0x%X]=load(%q),",depth,k,f))
+ else
+ handle(format("%s [%s]=load(%q),",depth,k,f))
+ end
+ elseif tk == "boolean" then
+ handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f))
+ elseif tk ~= "string" then
+ -- ignore
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=load(%q),",depth,k,f))
else
- handle(format("%s [%s]=load(%q),",depth,k,f))
+ handle(format("%s [%q]=load(%q),",depth,k,f))
end
- elseif tk == "boolean" then
- handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f))
- elseif tk ~= "string" then
- -- ignore
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s=load(%q),",depth,k,f))
- else
- handle(format("%s [%q]=load(%q),",depth,k,f))
end
end
else
@@ -958,7 +974,8 @@ end
-- number : [number] = { }
function table.serialize(root,name,specification)
- local t, n = { }, 0
+ local t = { }
+ local n = 0
local function flush(s)
n = n + 1
t[n] = s
@@ -982,13 +999,15 @@ function table.tofile(filename,root,name,specification)
local f = io.open(filename,'w')
if f then
if maxtab > 1 then
- local t, n = { }, 0
+ local t = { }
+ local n = 0
local function flush(s)
n = n + 1
t[n] = s
if n > maxtab then
f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t, n = { }, 0 -- we could recycle t if needed
+ t = { } -- we could recycle t if needed
+ n = 0
end
end
serialize(flush,root,name,specification)
@@ -1006,12 +1025,12 @@ end
local function flattened(t,f,depth) -- also handles { nil, 1, nil, 2 }
if f == nil then
- f = { }
+ f = { }
depth = 0xFFFF
elseif tonumber(f) then
-- assume that only two arguments are given
depth = f
- f = { }
+ f = { }
elseif not depth then
depth = 0xFFFF
end
@@ -1099,8 +1118,12 @@ local function are_equal(a,b,n,m) -- indexed
if a == b then
return true
elseif a and b and #a == #b then
- n = n or 1
- m = m or #a
+ if not n then
+ n = 1
+ end
+ if not m then
+ m = #a
+ end
for i=n,m do
local ai, bi = a[i], b[i]
if ai==bi then
@@ -1213,7 +1236,8 @@ end
function table.reversed(t)
if t then
- local tt, tn = { }, #t
+ local tt = { }
+ local tn = #t
if tn > 0 then
local ttn = 0
for i=tn,1,-1 do
@@ -1228,24 +1252,32 @@ end
function table.reverse(t) -- check with 5.3 ?
if t then
local n = #t
+ local m = n + 1
for i=1,floor(n/2) do -- maybe just n//2
- local j = n - i + 1
+ local j = m - i
t[i], t[j] = t[j], t[i]
end
return t
end
end
-function table.sequenced(t,sep,simple) -- hash only
+local function sequenced(t,sep,simple)
if not t then
return ""
+ elseif type(t) == "string" then
+ return t -- handy fallback
end
local n = #t
local s = { }
if n > 0 then
-- indexed
for i=1,n do
- s[i] = tostring(t[i])
+ local v = t[i]
+ if type(v) == "table" then
+ s[i] = "{" .. sequenced(v,sep,simple) .. "}"
+ else
+ s[i] = tostring(t[i])
+ end
end
else
-- hashed
@@ -1257,17 +1289,27 @@ function table.sequenced(t,sep,simple) -- hash only
s[n] = k
elseif v and v~= "" then
n = n + 1
- s[n] = k .. "=" .. tostring(v)
+ if type(v) == "table" then
+ s[n] = k .. "={" .. sequenced(v,sep,simple) .. "}"
+ else
+ s[n] = k .. "=" .. tostring(v)
+ end
end
else
n = n + 1
- s[n] = k .. "=" .. tostring(v)
+ if type(v) == "table" then
+ s[n] = k .. "={" .. sequenced(v,sep,simple) .. "}"
+ else
+ s[n] = k .. "=" .. tostring(v)
+ end
end
end
end
return concat(s,sep or " | ")
end
+table.sequenced = sequenced
+
function table.print(t,...)
if type(t) ~= "table" then
print(tostring(t))
@@ -1312,8 +1354,8 @@ end
function table.unique(old)
local hash = { }
- local new = { }
- local n = 0
+ local new = { }
+ local n = 0
for i=1,#old do
local oi = old[i]
if not hash[oi] then
@@ -1334,12 +1376,14 @@ end
function table.values(t,s) -- optional sort flag
if t then
- local values, keys, v = { }, { }, 0
+ local values = { }
+ local keys = { }
+ local v = 0
for key, value in next, t do
if not keys[value] then
v = v + 1
values[v] = value
- keys[k] = key
+ keys[k] = key
end
end
if s then
diff --git a/tex/context/base/mkiv/l-unicode.lua b/tex/context/base/mkiv/l-unicode.lua
index b5f52d312..13e0a3fa1 100644
--- a/tex/context/base/mkiv/l-unicode.lua
+++ b/tex/context/base/mkiv/l-unicode.lua
@@ -21,13 +21,33 @@ if not modules then modules = { } end modules ['l-unicode'] = {
-- todo: utf.sub replacement (used in syst-aux)
-- we put these in the utf namespace:
--- used : byte char gmatch len lower sub upper
--- not used : dump find format gfind gsub match rep reverse
+-- used : byte char len lower sub upper
+-- not used : dump find format gmatch gfind gsub match rep reverse
-utf = utf or (unicode and unicode.utf8) or { }
+-- utf = utf or (unicode and unicode.utf8) or { }
+
+-- not supported:
+--
+-- dump, find, format, gfind, gmatch, gsub, lower, match, rep, reverse, upper
+
+utf = utf or { }
+unicode = nil
+
+if not string.utfcharacters then
+
+ -- New: this gmatch hack is taken from the Lua 5.2 book. It's about two times slower
+ -- than the built-in string.utfcharacters.
+
+ local gmatch = string.gmatch
+
+ function string.characters(str)
+ return gmatch(str,".[\128-\191]*")
+ end
-utf.characters = utf.characters or string.utfcharacters
-utf.values = utf.values or string.utfvalues
+
+end
+
+utf.characters = string.utfcharacters
-- string.utfvalues
-- string.utfcharacters
@@ -53,23 +73,19 @@ local bytepairs = string.bytepairs
local finder = lpeg.finder
local replacer = lpeg.replacer
-local utfvalues = utf.values
-local utfgmatch = utf.gmatch -- not always present
-
local p_utftype = patterns.utftype
local p_utfstricttype = patterns.utfstricttype
local p_utfoffset = patterns.utfoffset
-local p_utf8char = patterns.utf8character
+local p_utf8character = patterns.utf8character
+local p_utf8char = patterns.utf8char
local p_utf8byte = patterns.utf8byte
local p_utfbom = patterns.utfbom
local p_newline = patterns.newline
local p_whitespace = patterns.whitespace
-if not unicode then
-
- unicode = { utf = utf } -- for a while
-
-end
+-- if not unicode then
+-- unicode = { utf = utf } -- for a while
+-- end
if not utf.char then
@@ -164,10 +180,8 @@ if not utf.byte then
if not utf.byte then
- local utf8byte = patterns.utf8byte
-
function utf.byte(c)
- return lpegmatch(utf8byte,c)
+ return lpegmatch(p_utf8byte,c)
end
end
@@ -281,7 +295,7 @@ if not utf.len then
-- -- alternative 1: 0.77
--
- -- local utfcharcounter = utfbom^-1 * Cs((p_utf8char/'!')^0)
+ -- local utfcharcounter = utfbom^-1 * Cs((p_utf8character/'!')^0)
--
-- function utf.len(str)
-- return #lpegmatch(utfcharcounter,str or "")
@@ -291,7 +305,7 @@ if not utf.len then
--
-- local n = 0
--
- -- local utfcharcounter = utfbom^-1 * (p_utf8char/function() n = n + 1 end)^0 -- slow
+ -- local utfcharcounter = utfbom^-1 * (p_utf8character/function() n = n + 1 end)^0 -- slow
--
-- function utf.length(str)
-- n = 0
@@ -368,7 +382,7 @@ if not utf.sub then
-- inefficient as lpeg just copies ^n
-- local function sub(str,start,stop)
- -- local pattern = p_utf8char^-(start-1) * C(p_utf8char^-(stop-start+1))
+ -- local pattern = p_utf8character^-(start-1) * C(p_utf8character^-(stop-start+1))
-- inspect(pattern)
-- return lpegmatch(pattern,str) or ""
-- end
@@ -391,7 +405,7 @@ if not utf.sub then
-- end
-- end
--
- -- local pattern = Cmt(p_utf8char,slide)^0
+ -- local pattern = Cmt(p_utf8character,slide)^0
--
-- function utf.sub(str,start,stop) -- todo: from the end
-- if not start then
@@ -446,11 +460,11 @@ if not utf.sub then
end
end
- local pattern_zero = Cmt(p_utf8char,slide_zero)^0
- local pattern_one = Cmt(p_utf8char,slide_one )^0
- local pattern_two = Cmt(p_utf8char,slide_two )^0
+ local pattern_zero = Cmt(p_utf8character,slide_zero)^0
+ local pattern_one = Cmt(p_utf8character,slide_one )^0
+ local pattern_two = Cmt(p_utf8character,slide_two )^0
- local pattern_first = C(patterns.utf8character)
+ local pattern_first = C(p_utf8character)
function utf.sub(str,start,stop)
if not start then
@@ -546,7 +560,7 @@ end
-- a replacement for simple gsubs:
-- function utf.remapper(mapping)
--- local pattern = Cs((p_utf8char/mapping)^0)
+-- local pattern = Cs((p_utf8character/mapping)^0)
-- return function(str)
-- if not str or str == "" then
-- return ""
@@ -568,16 +582,16 @@ function utf.remapper(mapping,option,action) -- static also returns a pattern
return ""
else
if not pattern then
- pattern = Cs((tabletopattern(mapping)/action + p_utf8char)^0)
+ pattern = Cs((tabletopattern(mapping)/action + p_utf8character)^0)
end
return lpegmatch(pattern,str)
end
end
elseif option == "pattern" then
- return Cs((tabletopattern(mapping)/action + p_utf8char)^0)
+ return Cs((tabletopattern(mapping)/action + p_utf8character)^0)
-- elseif option == "static" then
else
- local pattern = Cs((tabletopattern(mapping)/action + p_utf8char)^0)
+ local pattern = Cs((tabletopattern(mapping)/action + p_utf8character)^0)
return function(str)
if not str or str == "" then
return ""
@@ -588,9 +602,9 @@ function utf.remapper(mapping,option,action) -- static also returns a pattern
end
elseif variant == "function" then
if option == "pattern" then
- return Cs((p_utf8char/mapping + p_utf8char)^0)
+ return Cs((p_utf8character/mapping + p_utf8character)^0)
else
- local pattern = Cs((p_utf8char/mapping + p_utf8char)^0)
+ local pattern = Cs((p_utf8character/mapping + p_utf8character)^0)
return function(str)
if not str or str == "" then
return ""
@@ -637,9 +651,9 @@ end
-- inspect(utf.split("a b c d",true))
local utflinesplitter = p_utfbom^-1 * lpeg.tsplitat(p_newline)
-local utfcharsplitter_ows = p_utfbom^-1 * Ct(C(p_utf8char)^0)
-local utfcharsplitter_iws = p_utfbom^-1 * Ct((p_whitespace^1 + C(p_utf8char))^0)
-local utfcharsplitter_raw = Ct(C(p_utf8char)^0)
+local utfcharsplitter_ows = p_utfbom^-1 * Ct(C(p_utf8character)^0)
+local utfcharsplitter_iws = p_utfbom^-1 * Ct((p_whitespace^1 + C(p_utf8character))^0)
+local utfcharsplitter_raw = Ct(C(p_utf8character)^0)
patterns.utflinesplitter = utflinesplitter
@@ -775,7 +789,7 @@ local utf_32_le_linesplitter = utf_32_le_getbom * lpeg.tsplitat(patterns.utf_32_
-- if right then
-- local now = 256*left + right
-- if more > 0 then
--- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
+-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
-- more = 0
-- r = r + 1
-- result[r] = utfchar(now)
@@ -804,7 +818,7 @@ local utf_32_le_linesplitter = utf_32_le_getbom * lpeg.tsplitat(patterns.utf_32_
-- if right then
-- local now = 256*right + left
-- if more > 0 then
--- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
+-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
-- more = 0
-- r = r + 1
-- result[r] = utfchar(now)
@@ -834,7 +848,7 @@ local utf_32_le_linesplitter = utf_32_le_getbom * lpeg.tsplitat(patterns.utf_32_
-- if right then
-- local now = 256*right + left
-- if more > 0 then
--- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
+-- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
-- more = 0
-- r = r + 1
-- result[r] = utfchar(now)
@@ -911,7 +925,7 @@ local more = 0
local p_utf16_to_utf8_be = C(1) * C(1) /function(left,right)
local now = 256*byte(left) + byte(right)
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
more = 0
return utfchar(now)
elseif now >= 0xD800 and now <= 0xDBFF then
@@ -925,7 +939,7 @@ end
local p_utf16_to_utf8_le = C(1) * C(1) /function(right,left)
local now = 256*byte(left) + byte(right)
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
more = 0
return utfchar(now)
elseif now >= 0xD800 and now <= 0xDBFF then
@@ -1119,15 +1133,6 @@ function utf.utf8_to_utf16(str,littleendian,nobom)
end
end
--- function utf.tocodes(str,separator) -- can be sped up with an lpeg
--- local t, n = { }, 0
--- for u in utfvalues(str) do
--- n = n + 1
--- t[n] = format("0x%04X",u)
--- end
--- return concat(t,separator or " ")
--- end
-
local pattern = Cs (
(p_utf8byte / function(unicode ) return format( "0x%04X", unicode) end) *
(p_utf8byte * Carg(1) / function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0
@@ -1163,25 +1168,10 @@ end
--
-local p_nany = p_utf8char / ""
-
-if utfgmatch then
-
- function utf.count(str,what)
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #lpegmatch(Cs((P(what)/" " + p_nany)^0),str)
- end
- end
-
-else
+do
- local cache = { }
+ local p_nany = p_utf8character / ""
+ local cache = { }
function utf.count(str,what)
if type(what) == "string" then
@@ -1198,23 +1188,7 @@ else
end
--- maybe also register as string.utf*
-
-
-if not utf.characters then
-
- -- New: this gmatch hack is taken from the Lua 5.2 book. It's about two times slower
- -- than the built-in string.utfcharacters.
-
- function utf.characters(str)
- return gmatch(str,".[\128-\191]*")
- end
-
- string.utfcharacters = utf.characters
-
-end
-
-if not utf.values then
+if not string.utfvalues then
-- So, a logical next step is to check for the values variant. It over five times
-- slower than the built-in string.utfvalues. I optimized it a bit for n=0,1.
@@ -1226,7 +1200,7 @@ if not utf.values then
-- we share this one
end
- -- function utf.values(str)
+ -- function string.utfvalues(str)
-- local n = #str
-- if n == 0 then
-- return wrap(dummy)
@@ -1241,7 +1215,7 @@ if not utf.values then
--
-- faster:
- function utf.values(str)
+ function string.utfvalues(str)
local n = #str
if n == 0 then
return dummy
@@ -1264,11 +1238,11 @@ if not utf.values then
-- slower:
--
- -- local pattern = C(patterns.utf8character) * Cp()
- -- ----- pattern = patterns.utf8character/utfbyte * Cp()
- -- ----- pattern = patterns.utf8byte * Cp()
+ -- local pattern = C(p_utf8character) * Cp()
+ -- ----- pattern = p_utf8character/utfbyte * Cp()
+ -- ----- pattern = p_utf8byte * Cp()
--
- -- function utf.values(str) -- one of the cases where a find is faster than an lpeg
+ -- function string.utfvalues(str) -- one of the cases where a find is faster than an lpeg
-- local n = #str
-- if n == 0 then
-- return dummy
@@ -1287,10 +1261,10 @@ if not utf.values then
-- end
-- end
- string.utfvalues = utf.values
-
end
+utf.values = string.utfvalues
+
function utf.chrlen(u) -- u is number
return
(u < 0x80 and 1) or
@@ -1310,7 +1284,7 @@ if bit32 then
local extract = bit32.extract
local char = string.char
- function unicode.toutf32string(n)
+ function utf.toutf32string(n)
if n <= 0xFF then
return
char(n) ..
@@ -1359,3 +1333,73 @@ function string.utfpadd(s,n)
end
return s
end
+
+-- goodies
+
+do
+
+ local utfcharacters = utf.characters or string.utfcharacters
+ local utfchar = utf.char or string.utfcharacter
+
+ lpeg.UP = P
+
+ if utfcharacters then
+
+ function lpeg.US(str)
+ local p = P(false)
+ for uc in utfcharacters(str) do
+ p = p + P(uc)
+ end
+ return p
+ end
+
+ else
+
+ function lpeg.US(str)
+ local p = P(false)
+ local f = function(uc)
+ p = p + P(uc)
+ end
+ lpegmatch((p_utf8char/f)^0,str)
+ return p
+ end
+
+ end
+
+ local range = p_utf8byte * p_utf8byte + Cc(false) -- utf8byte is already a capture
+
+ function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = lpegmatch(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ end
+ if not utfchar then
+ utfchar = utf.char -- maybe delayed
+ end
+ if utfchar and (last - first < 8) then -- a somewhat arbitrary criterium
+ local p = P(false)
+ for i=first,last do
+ p = p + P(utfchar(i))
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ -- tricky, these nested captures
+ return p_utf8byte / f -- nil when invalid range
+ end
+ end
+
+ -- print(lpeg.match(lpeg.Cs((C(lpeg.UR("αω"))/{ ["χ"] = "OEPS" })^0),"αωχαω"))
+
+end
diff --git a/tex/context/base/mkiv/lang-def.lua b/tex/context/base/mkiv/lang-def.lua
index c0c3981f7..3f04bed0d 100644
--- a/tex/context/base/mkiv/lang-def.lua
+++ b/tex/context/base/mkiv/lang-def.lua
@@ -225,6 +225,15 @@ local specifications = allocate {
["variant"] = "fi",
},
{
+ ["description"] = "Estonian",
+ ["script"] = "latn",
+ ["bibliographical"] = "est",
+ ["terminological"] = "est",
+ ["context"] = "et",
+ ["opentype"] = "est",
+ ["variant"] = "et",
+ },
+ {
["description"] = "French",
["script"] = "latn",
["bibliographical"] = "fre",
diff --git a/tex/context/base/mkiv/lang-def.mkiv b/tex/context/base/mkiv/lang-def.mkiv
index 28245e591..7f3e85f08 100644
--- a/tex/context/base/mkiv/lang-def.mkiv
+++ b/tex/context/base/mkiv/lang-def.mkiv
@@ -22,19 +22,6 @@
% Frisian, Plattdeutsch
\installlanguage
- [\s!nl]
- [\c!spacing=\v!packed,
- \c!leftsentence=\emdash,
- \c!rightsentence=\emdash,
- \c!leftsubsentence=\emdash,
- \c!rightsubsentence=\emdash,
- \c!leftquote=\lowerleftsingleninequote,
- \c!rightquote=\upperrightsingleninequote,
- \c!leftquotation=\lowerleftdoubleninequote,
- \c!rightquotation=\upperrightdoubleninequote,
- \c!date={\v!day,\space,\v!month,\space,\v!year}]
-
-\installlanguage
[\s!en]
[\c!spacing=\v!broad,
\c!leftsentence=\emdash,
@@ -51,6 +38,19 @@
\s!righthyphenmin=3]
\installlanguage
+ [\s!nl]
+ [\c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\lowerleftsingleninequote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\lowerleftdoubleninequote,
+ \c!rightquotation=\upperrightdoubleninequote,
+ \c!date={\v!day,\space,\v!month,\space,\v!year}]
+
+\installlanguage
[\s!de]
[\c!spacing=\v!packed,
\s!lefthyphenmin=3,
@@ -328,6 +328,22 @@
\c!date={\v!year,\space,\v!month,\space,\v!day}]
\installlanguage
+ [\s!et]
+ [\c!default=\s!en,
+ \c!spacing=\v!packed,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\leftguillemot,
+ \c!rightquote=\rightguillemot,
+ \c!leftquotation=\lowerrightdoubleninequote,
+ \c!rightquotation=\upperrightdoublesixquote,
+ \c!time={h,{.},m},
+ \c!date={\v!day,.,\space,\v!month,\space,\v!year},
+ \s!patterns=\s!et]
+
+\installlanguage
[\s!hu]
[\c!spacing=\v!packed,
\c!leftsentence=\emdash,
@@ -341,6 +357,7 @@
\c!date={\v!year,.,\space,\v!month,\space,\v!day,.}]
\installlanguage [\s!finnish] [\s!fi]
+\installlanguage [\s!estonian] [\s!et]
\installlanguage [\s!hungarian] [\s!hu]
% Altaic Languages: Uigur, Uzbek, Azeri/Azerbaijani, Chuvash,
@@ -580,6 +597,7 @@
\c!rightquote=\rightguillemot,
\c!leftquotation=\leftguillemot,
\c!rightquotation=\rightguillemot,
+ \c!time={h,{\Uchar104 },m},% we need to cheat in order to get the h
\c!date={\v!day:mnem,\v!space,\v!month,\v!space,\v!year}]
\installlanguage
diff --git a/tex/context/base/mkiv/lang-dis.lua b/tex/context/base/mkiv/lang-dis.lua
index 65a53a702..5603d1193 100644
--- a/tex/context/base/mkiv/lang-dis.lua
+++ b/tex/context/base/mkiv/lang-dis.lua
@@ -17,14 +17,10 @@ local nuts = nodes.nuts
local enableaction = tasks.enableaction
local setaction = tasks.setaction
-local tonode = nuts.tonode
-local tonut = nuts.tonut
-
local setfield = nuts.setfield
local getnext = nuts.getnext
local getprev = nuts.getprev
local getid = nuts.getid
-local getfont = nuts.getfont
local getattr = nuts.getattr
local getsubtype = nuts.getsubtype
local setsubtype = nuts.setsubtype
@@ -40,10 +36,11 @@ local isglyph = nuts.isglyph
local copy_node = nuts.copy
local remove_node = nuts.remove
-local traverse_id = nuts.traverse_id
local flush_list = nuts.flush_list
local flush_node = nuts.flush_node
+local nextdisc = nuts.traversers.disc
+
local new_disc = nuts.pool.disc
local nodecodes = nodes.nodecodes
@@ -52,10 +49,7 @@ local disccodes = nodes.disccodes
local disc_code = nodecodes.disc
local glyph_code = nodecodes.glyph
-local discretionary_code = disccodes.discretionary
-local explicit_code = disccodes.explicit
-local automatic_code = disccodes.automatic
-local regular_code = disccodes.regular
+local explicitdisc_code = disccodes.explicit
local a_visualize = attributes.private("visualizediscretionary")
local setattribute = tex.setattribute
@@ -69,7 +63,7 @@ local check_regular = true
local setlistcolor = nodes.tracers.colors.setlist
function languages.visualizediscretionaries(head)
- for d in traverse_id(disc_code,tonut(head)) do
+ for d in nextdisc, head do
if getattr(d,a_visualize) then
local pre, post, replace = getdisc(d)
if pre then
@@ -83,6 +77,7 @@ function languages.visualizediscretionaries(head)
end
end
end
+ return head
end
local enabled = false
@@ -129,13 +124,9 @@ end
local wiped = 0
-local flatten_discretionaries = node.flatten_discretionaries -- todo in nodes
+local flatten_discretionaries = nuts.flatten_discretionaries -- todo in nodes
-if flatten_discretionaries then
-
- -- This is not that much faster than the lua variant simply because there is
- -- seldom a replace list but it fits in the picture. See luatex-todo.w for the
- -- code.
+-- if flatten_discretionaries then
function languages.flatten(head)
local h, n = flatten_discretionaries(head)
@@ -143,51 +134,50 @@ if flatten_discretionaries then
return h, n > 0
end
-else
-
- local function wipe(head,delayed)
- local p, n = getboth(delayed)
- local _, _, h, _, _, t = getdisc(delayed,true)
- if p or n then
- if h then
- setlink(p,h)
- setlink(t,n)
- setfield(delayed,"replace")
- else
- setlink(p,n)
- end
- end
- if head == delayed then
- head = h
- end
- wiped = wiped + 1
- flush_node(delayed)
- return head
- end
-
- function languages.flatten(head)
- local nuthead = tonut(head)
- local delayed = nil
- for d in traverse_id(disc_code,nuthead) do
- if delayed then
- nuthead = wipe(nuthead,delayed)
- end
- delayed = d
- end
- if delayed then
- return tonode(wipe(nuthead,delayed)), true
- else
- return head, false
- end
- end
-
-end
+-- else
+--
+-- local function wipe(head,delayed)
+-- local p, n = getboth(delayed)
+-- local _, _, h, _, _, t = getdisc(delayed,true)
+-- if p or n then
+-- if h then
+-- setlink(p,h)
+-- setlink(t,n)
+-- setfield(delayed,"replace")
+-- else
+-- setlink(p,n)
+-- end
+-- end
+-- if head == delayed then
+-- head = h
+-- end
+-- wiped = wiped + 1
+-- flush_node(delayed)
+-- return head
+-- end
+--
+-- function languages.flatten(head)
+-- local delayed = nil
+-- for d in nextdisc, head do
+-- if delayed then
+-- head = wipe(head,delayed)
+-- end
+-- delayed = d
+-- end
+-- if delayed then
+-- return wipe(head,delayed), true
+-- else
+-- return head, false
+-- end
+-- end
+--
+-- end
function languages.nofflattened()
return wiped -- handy for testing
end
--- experiment
+-- experiment: for now not in not in export mode!
local flatten = languages.flatten
local getlist = nodes.getlist
@@ -198,10 +188,11 @@ function nodes.handlers.flatten(head,where)
if head and (where == "box" or where == "adjusted_hbox") then
return flatten(head)
end
- return true
+ return head
end
directives.register("hyphenator.flatten",function(v)
+ -- use with care
setaction("processors","nodes.handlers.flatten",v)
setaction("contributers","nodes.handlers.flattenline",v)
end)
@@ -227,6 +218,6 @@ function languages.explicithyphen(template)
end
end
end
- setdisc(disc,pre,post,nil,explicit_code,tex.exhyphenpenalty)
+ setdisc(disc,pre,post,nil,explicitdisc_code,tex.exhyphenpenalty)
return disc
end
diff --git a/tex/context/base/mkiv/lang-exp.lua b/tex/context/base/mkiv/lang-exp.lua
index 70fad48b0..254961ee6 100644
--- a/tex/context/base/mkiv/lang-exp.lua
+++ b/tex/context/base/mkiv/lang-exp.lua
@@ -31,6 +31,8 @@ local expanders -- this will go away
if LUATEXVERSION < 1.005 then -- not loaded any more
+ -- some shortcuts go here
+
expanders = {
[discretionary_code] = function(d,template)
-- \discretionary
@@ -172,23 +174,23 @@ languages.expanders = expanders
----- expand_explicit = expanders and expanders[explicit_code]
----- expand_automatic = expanders and expanders[automatic_code]
-if LUATEXVERSION < 1.005 then -- not loaded any more
-
- expanded = function(head)
- local done = hyphenate(head)
- if done then
- for d in traverse_id(disc_code,tonut(head)) do
- local s = getsubtype(d)
- if s ~= discretionary_code then
- expanders[s](d,template)
- done = true
- end
- end
- end
- return head, done
- end
-
-end
+-- if LUATEXVERSION < 1.005 then -- not loaded any more
+--
+-- expanded = function(head)
+-- local done = hyphenate(head)
+-- if done then
+-- for d in traverse_id(disc_code,head) do
+-- local s = getsubtype(d)
+-- if s ~= discretionary_code then
+-- expanders[s](d,template)
+-- done = true
+-- end
+-- end
+-- end
+-- return head, done
+-- end
+--
+-- end
-- if id == disc_code then
-- if expanded then
diff --git a/tex/context/base/mkiv/lang-hyp.lua b/tex/context/base/mkiv/lang-hyp.lua
index e29446b65..92b400d4f 100644
--- a/tex/context/base/mkiv/lang-hyp.lua
+++ b/tex/context/base/mkiv/lang-hyp.lua
@@ -626,13 +626,10 @@ if context then
local math_code = nodecodes.math
local hlist_code = nodecodes.hlist
- local discretionary_code = disccodes.discretionary
- local explicit_code = disccodes.explicit
- local automatic_code = disccodes.automatic
- local regular_code = disccodes.regular
+ local automaticdisc_code = disccodes.automatic
+ local regulardisc_code = disccodes.regular
local nuts = nodes.nuts
- local tonut = nodes.tonut
local tonode = nodes.tonode
local nodepool = nuts.pool
@@ -666,7 +663,9 @@ if context then
local remove_node = nuts.remove
local end_of_math = nuts.end_of_math
local node_tail = nuts.tail
- local traverse_id = nuts.traverse_id
+
+ local nexthlist = nuts.traversers.hlist
+ local nextdisc = nuts.traversers.disc
local setcolor = nodes.tracers.colors.set
@@ -1028,9 +1027,7 @@ featureset.hyphenonly = hyphenonly == v_yes
function traditional.hyphenate(head)
- local first = tonut(head)
-
-
+ local first = head
local tail = nil
local last = nil
local current = first
@@ -1289,7 +1286,7 @@ featureset.hyphenonly = hyphenonly == v_yes
if leftchar then
post = serialize(true,leftchar)
end
- setdisc(disc,pre,post,nil,regular_code,hyphenpenalty)
+ setdisc(disc,pre,post,nil,regulardisc_code,hyphenpenalty)
if attrnode then
setattrlist(disc,attrnode)
end
@@ -1324,7 +1321,7 @@ featureset.hyphenonly = hyphenonly == v_yes
end
end
-- maybe regular code
- setdisc(disc,pre,post,replace,regular_code,hyphenpenalty)
+ setdisc(disc,pre,post,replace,regulardisc_code,hyphenpenalty)
if attrnode then
setattrlist(disc,attrnode)
end
@@ -1364,7 +1361,7 @@ featureset.hyphenonly = hyphenonly == v_yes
end
pre = copy_node(glyph)
setchar(pre,rightchar and rightchar > 0 and rightchar or code)
- setdisc(disc,pre,post,replace,automatic_code,hyphenpenalty) -- ex ?
+ setdisc(disc,pre,post,replace,automaticdisc_code,hyphenpenalty) -- ex ?
if attrnode then
setattrlist(disc,attrnode)
end
@@ -1386,7 +1383,7 @@ featureset.hyphenonly = hyphenonly == v_yes
local pre = copy_list(start)
local post = nil
local replace = start
- setdisc(disc,pre,post,replace,automatic_code,hyphenpenalty) -- ex ?
+ setdisc(disc,pre,post,replace,automaticdisc_code,hyphenpenalty) -- ex ?
if attrnode then
setattrlist(disc,attrnode)
end
@@ -1585,7 +1582,7 @@ featureset.hyphenonly = hyphenonly == v_yes
stoptiming(traditional)
- return head, true
+ return head
end
statistics.register("hyphenation",function()
@@ -1613,15 +1610,31 @@ featureset.hyphenonly = hyphenonly == v_yes
-- local replaceaction = nodes.tasks.replaceaction -- no longer overload this way (too many local switches)
- local hyphenate = lang.hyphenate
- local methods = { }
- local usedmethod = false
- local stack = { }
+ local hyphenate = lang.hyphenate
+ local hyphenating = nuts.hyphenating
+ local methods = { }
+ local usedmethod = false
+ local stack = { }
- local function original(head)
- local done = hyphenate(head)
- return head, done
- end
+ local original = hyphenating and
+ function(head)
+ return (hyphenating(head))
+ end
+ or
+ function(head)
+ hyphenate(tonode(head))
+ return head -- a nut
+ end
+
+ -- local has_language = lang.has_language
+ --
+ -- local function original(head) -- kernel.hyphenation(head)
+ -- local h = tonode(head)
+ -- if has_language(h) then
+ -- hyphenate(h)
+ -- end
+ -- return head
+ -- end
local getcount = tex.getcount
@@ -1637,13 +1650,13 @@ featureset.hyphenonly = hyphenonly == v_yes
forced = false
return usedmethod(head)
else
- return head, false
+ return head
end
else
return usedmethod(head)
end
else
- return head, false
+ return head
end
end
@@ -1729,13 +1742,12 @@ featureset.hyphenonly = hyphenonly == v_yes
}
function nodes.stripdiscretionaries(head)
- local h = tonut(head)
- for l in traverse_id(hlist_code,h) do
- for d in traverse_id(disc_code,getlist(l)) do
+ for l in nexthlist, head do
+ for d in nextdisc, getlist(l) do
remove_node(h,false,true)
end
end
- return tonode(h)
+ return head
end
diff --git a/tex/context/base/mkiv/lang-hyp.mkiv b/tex/context/base/mkiv/lang-hyp.mkiv
index feec82659..9301fd1d8 100644
--- a/tex/context/base/mkiv/lang-hyp.mkiv
+++ b/tex/context/base/mkiv/lang-hyp.mkiv
@@ -48,10 +48,11 @@
\automatichyphenmode \plusone
\hyphenpenaltymode \plusfour
-\hyphenpenalty 50 % hyphenator
-\automatichyphenpenalty 50 % -
-\explicithyphenpenalty 50 % \-
-\compoundhyphenpenalty 50
+\hyphenpenalty 50 % hyphenator
+\automatichyphenpenalty 50 % -
+\explicithyphenpenalty 50 % \-
+\compoundhyphenpenalty 50
+\exceptionpenalty 1000
%D This command can change! At some point we will keep the setting with the
%D paragraph and then the \type {\par} can go.
diff --git a/tex/context/base/mkiv/lang-ini.mkiv b/tex/context/base/mkiv/lang-ini.mkiv
index 7c83ae38f..296cf7f1c 100644
--- a/tex/context/base/mkiv/lang-ini.mkiv
+++ b/tex/context/base/mkiv/lang-ini.mkiv
@@ -15,10 +15,10 @@
% \cldcontext{languages.numbers[tex.count.mainlanguagenumber]}
-%D This module implements the (for the moment still simple)
-%D multi||language support of \CONTEXT, which should not be
-%D confused with the multi||lingual interface. This support
-%D will be extended when needed.
+%D This module implements multi||language support of \CONTEXT, which should not be
+%D confused with the multi||lingual interface. This support will be extended when
+%D needed. Properties of languages are defined in \TEX\ files as well as \LUA\
+%D files.
\writestatus{loading}{ConTeXt Language Macros / Initialization}
@@ -28,41 +28,27 @@
\unprotect
-% \def\testlanguage[#1]%
-% {\start
-% \language[#1]
-% \number\normallanguage/\the\lefthyphenmin/\the\righthyphenmin:
-% \input tufte
-% \hyphenatedword{effetestenofditwerkt}
-% \par
-% \stop}
-%
-% \testlanguage[de] \testlanguage[de-de] \testlanguage[de-at] \testlanguage[de-ch] \page
-% \testlanguage[en] \testlanguage[us] \testlanguage[en-us] \testlanguage[uk] \testlanguage[en-gb] \page
-
\ifdefined\nonfrenchspacing\else \let\nonfrenchspacing\relax \fi
\ifdefined\frenchspacing \else \let\frenchspacing \relax \fi
-%D When loading hyphenation patterns, \TEX\ assign a number to
-%D each loaded table, starting with~0. Switching to a specific
-%D table is done by assigning the relevant number to the
-%D predefined \COUNTER\ \type{\language}.
+%D When loading hyphenation patterns, \TEX\ assign a number to each loaded table,
+%D starting with~0. Switching to a specific table is done by assigning the relevant
+%D number to the predefined \COUNTER\ \type {\language}. However, in \MKIV\ a lot
+%D of management is delegated to \LUA.
-%D We keep track of the last loaded patterns by means of a
-%D pseudo \COUNTER. This just one of those situations in which
-%D we don't want to spent a real one. Language zero has no
-%D patterns, first of all because I like to start numbering
-%D at one. It may come in handy for special purposes as well.
+%D We keep track of the last loaded patterns by means of a pseudo \COUNTER. This
+%D just one of those situations in which we don't want to spent a real one. Language
+%D zero has no patterns, first of all because I like to start numbering at one. It
+%D may come in handy for special purposes as well.
\normallanguage\zerocount \def\loadedlanguage{1}
%D \macros
%D {currentlanguage, setupcurrentlanguage}
%D
-%D Instead of numbers,we are going to use symbolic names for
-%D the languages. The current langage is saved in the macro
-%D \type {\currentlanguage}. The setup macro is mainly used
-%D for cosmetic purposes.
+%D Instead of numbers,we are going to use symbolic names for the languages. The
+%D current langage is saved in the macro \type {\currentlanguage}. The setup macro
+%D is mainly used for cosmetic purposes.
%D
%D \starttyping
%D \dorecurse{3}
@@ -79,10 +65,9 @@
%D \macros
%D {defaultlanguage,languageparameter,specificlanguageparameter}
-
-%D We don't use the commandhandler here (yet) because we have
-%D a rather special fallback mechanism so quite some compatibility
-%D testing is needed.
+%D
+%D We don't use the commandhandler here (yet) because we have a rather special
+%D fallback mechanism so quite some compatibility testing is needed.
\installcorenamespace{language}
\installcorenamespace{languagelinked}
@@ -96,33 +81,6 @@
#1%
\fi}
-% \def\languageparameter#1%
-% {\ifcsname\??language\currentlanguage#1\endcsname
-% \csname\??language\currentlanguage#1\endcsname
-% \else\ifcsname\??language\currentlanguage\s!default\endcsname
-% \expandafter\specificlanguageparameter\csname\??language\currentlanguage\s!default\endcsname{#1}%
-% \else\ifcsname\??language\s!default#1\endcsname
-% \csname\??language\s!default#1\endcsname
-% \fi\fi\fi}
-%
-% \def\specificlanguageparameter#1#2%
-% {\ifcsname\??language#1#2\endcsname
-% \csname\??language#1#2\endcsname
-% \else\ifcsname\??language#1\s!default\endcsname
-% \expandafter\specificlanguageparameter\csname\??language#1\s!default\endcsname{#2}%
-% \else\ifcsname\??language\s!default#2\endcsname
-% \csname\??language\s!default#2\endcsname
-% \fi\fi\fi}
-%
-% \def\mainlanguageparameter#1%
-% {\ifcsname\??language\currentmainlanguage#1\endcsname
-% \csname\??language\currentmainlanguage#1\endcsname
-% \else\ifcsname\??language\currentmainlanguage\s!default\endcsname
-% \expandafter\specificlanguageparameter\csname\??language\currentmainlanguage\s!default\endcsname{#1}%
-% \else\ifcsname\??language\s!default#1\endcsname
-% \csname\??language\s!default#1\endcsname
-% \fi\fi\fi}
-
\def\languageparameter#1%
{\ifcsname\??language\currentlanguage#1\endcsname
\lastnamedcs
@@ -152,15 +110,6 @@
\let\usedlanguageparameter\languageparameter
-% \def\askedlanguageparameter#1% assumes \currentusedlanguage being set
-% {\ifcsname\??language\currentusedlanguage#1\endcsname
-% \csname\??language\currentusedlanguage#1\endcsname
-% \else\ifcsname\??language\currentusedlanguage\s!default\endcsname
-% \expandafter\specificlanguageparameter\csname\??language\currentusedlanguage\s!default\endcsname{#1}%
-% \else\ifcsname\??language\s!default#1\endcsname
-% \csname\??language\s!default#1\endcsname
-% \fi\fi\fi}
-
\def\askedlanguageparameter#1% assumes \currentusedlanguage being set
{\ifcsname\??language\currentusedlanguage#1\endcsname
\lastnamedcs
@@ -171,7 +120,6 @@
\fi\fi\fi}
\unexpanded\def\setusedlanguage#1%
-% {\edef\currentusedlanguage{\reallanguagetag{#1\c!language}}%
{\edef\currentusedlanguage{\reallanguagetag{#1}}%
\ifx\currentusedlanguage\empty
\let\currentusedlanguage \currentlanguage
@@ -208,43 +156,23 @@
%D \macros
%D {installlanguage}
%D
-%D Hyphenation patterns can only be loaded when the format file
-%D is prepared. The next macro takes care of this loading. A
-%D language is specified with
+%D Hyphenation patterns can only be loaded when the format file is prepared. The
+%D next macro takes care of this loading. A language is specified with
%D
%D \showsetup{installlanguage}
%D
-%D When \type {state} equals \type {start}, both patterns
-%D and additional hyphenation specifications are loaded. These
-%D files are seached for on the system path and are to be
-%D named:
-%D
-%D \starttyping
-%D lang-identifier.\f!patternsextension
-%D lang-identifier.\f!hyhensextension
-%D \stoptyping
+%D When \type {state} equals \type {start}, both patterns and additional hyphenation
+%D specifications are loaded. These files are seached for in the patterns path
+%D have names like \type {lang-nl.lua}.
%D
-%D The \type{spacing} variable specifies how the spaces after
-%D punctuation has to be handled. English is by tradition more
-%D tolerant to inter||sentence spacing than other languages.
-%D
-%D This macro also defines \type {\identifier} as a shortcut
-%D switch to the language. Furthermore the command defined as
-%D being language specific, are executed. With
-%D \type {default} we can default to another language
-%D (patterns) at format generation time. This default language
-%D is overruled when the appropriate patterns are loaded (some
-%D implementations support run time addition of patterns to a
-%D preloaded format).
-
-%D \macros
-%D {preloadlanguages}
+%D The \type {spacing} variable specifies how the spaces after punctuation has to be
+%D handled. English is by tradition more tolerant to inter||sentence spacing than
+%D other languages.
%D
-%D We first try to load the files defined as file synonym
-%D for \type {lang-*.pat} and \type {lang-*.hyp}. After that we
-%D fall back on those files. The macro \type {\preloadpatterns}
-%D reports which patterns are loaded and what hyphenmin
-%D values are set.
+%D This macro also defines \type {\identifier} as a shortcut switch to the language.
+%D Furthermore the command defined as being language specific, are executed. With
+%D \type {default} we can default to another language (patterns) at format
+%D generation time. Patterns are loaded at runtime.
\newtoks \everysetuplanguage
@@ -260,7 +188,6 @@
\let\doiflanguageelse\doifelselanguage
\def\reallanguagetag#1%
- %{\ifcsname\??languagelinked#1\endcsname\csname\??languagelinked#1\endcsname\else#1\fi}
{\ifcsname\??languagelinked#1\endcsname\lastnamedcs\else#1\fi}
% \language[#1] gave unwanted side effect of loading language specifics
@@ -285,10 +212,9 @@
\def\lang_basics_install_indeed#1#2%
{\ifcsname#1\endcsname\else\setuvalue{#1}{\lang_basics_set_current[#2]}\fi}
-%D When the second argument is a language identifier, a
-%D synonym is created. This feature is present because we
-%D used dutch mnemonics in the dutch version, but nowadays
-%D conform a standard.
+%D When the second argument is a language identifier, a synonym is created. This
+%D feature is present because we used dutch mnemonics in the dutch version, but
+%D nowadays conform a standard.
\unexpanded\def\doifelsepatterns#1%
{\begingroup % will change
@@ -317,13 +243,15 @@
\let\lang_basics_synchronize\relax % be nice for setups till we have one
\fi
+\installmacrostack\currentlanguage
+
\def\lang_basics_setup[#1][#2]%
{\ifsecondargument
- \pushmacro\currentlanguage % can be default
+ \push_macro_currentlanguage % can be default
\edef\currentsetuplanguage{\reallanguagetag{#1}}%
\getparameters[\??language\currentsetuplanguage][#2]%
\the\everysetuplanguage
- \popmacro\currentlanguage
+ \pop_macro_currentlanguage
%\doif\currentsetuplanguage\currentlanguage we can have influenced inheritance (default)
\else
\let\currentsetuplanguage\currentlanguage
@@ -364,6 +292,7 @@
\c!middlespeech=,
\c!rightspeech=\languageparameter\c!rightquotation,
\c!limittext=\unknown,
+ \c!time={h,:,m},
\c!date={\v!year,\ ,\v!month,\ ,\v!day},
\c!text=Ag,
\s!font=] % \v!auto : experimental !
@@ -374,26 +303,21 @@
% [\s!default]
% [\c!righthyphenchar="AD]
-%D The values \type {leftsentence} and \type
-%D {rightsentence} can be (and are) used to implement
-%D automatic subsentence boundary glyphs, like in {\fr
-%D |<|french guillemots|>|} or {\de |<|german guillemots|>|} or
-%D {\nl |<|dutch dashes|>|} like situations. Furthermore \type
-%D {leftquotation} and \type {leftquote} come into view
-%D \quotation {when we quote} or \quote {quote} something.
+%D The values \type {leftsentence} and \type {rightsentence} can be (and are) used
+%D to implement automatic subsentence boundary glyphs, like in {\fr |<|french
+%D guillemots|>|} or {\de |<|german guillemots|>|} or {\nl |<|dutch dashes|>|} like
+%D situations. Furthermore \type {leftquotation} and \type {leftquote} come into
+%D view \quotation {when we quote} or \quote {quote} something.
%D \macros
-%D {currentdatespecification}
+%D {currentdatespecification, currenttimespecification}
%D
-%D Just to make things easy we can ask for the current date
-%D specification by saying:
+%D Just to make things easy we can ask for the current date specification by saying:
\def\currentdatespecification{\languageparameter\c!date}
+\def\currenttimespecification{\languageparameter\c!time}
-%D This command is not meant for users.
-
-%D Carefull reading of these macros shows that it's legal to
-%D say
+%D Carefull reading of these macros shows that it's legal to say
%D
%D \starttyping
%D \installlanguage [du] [de]
@@ -402,54 +326,39 @@
%D \macros
%D {language,mainlanguage}
%D
-%D Switching to another language (actually another hyphenation
-%D pattern) is done with:
+%D Switching to another language (actually another hyphenation pattern) is done
+%D with:
%D
%D \starttyping
%D \language[identifier]
%D \stoptyping
%D
-%D or with \type{\identifier}. Just to be compatible with
-%D \PLAIN\ \TEX, we still support the original meaning, so
+%D or with \type {\identifier}. Just to be compatible with \PLAIN\ \TEX, we still
+%D support the original meaning, so
%D
%D \starttyping
%D \language=1
%D \stoptyping
%D
-%D is a valid operation, where the relation between number
-%D and language depends on the order in installing languages.
+%D is a valid operation, where the relation between number and language depends on
+%D the order in installing languages.
%D
%D \showsetup{language}
%D \showsetup{mainlanguage}
%D
-%D Both commands take a predefined language identifier as
-%D argument. We can use \type{\mainlanguage[identifier]} for
-%D setting the (indeed) main language. This is the language
-%D used for translating labels like {\em figure} and {\em
-%D table}. The main language defaults to the current language.
-%D
-%D We take care of local as well as standardized language
-%D switching (fr and fa, de and du, but nl and nl).
+%D Both commands take a predefined language identifier as argument. We can use \type
+%D {\mainlanguage[identifier]} for setting the (indeed) main language. This is the
+%D language used for translating labels like {\em figure} and {\em table}. The main
+%D language defaults to the current language.
\newtoks \everylanguage
-% \def\lang_basics_synchronize% assumes that \currentlanguage is set % % % use different name as complex
-% {\normallanguage\ctxcommand{languagenumber(%
-% "\currentlanguage",%
-% "\defaultlanguage\currentlanguage",%
-% "\languageparameter\s!patterns"%
-% )}\relax
-% \the\everylanguage\relax}
-
-% (some 20%) faster but code jungle (the publication code can have excessive
-% switching
-
\installcorenamespace{languagenumbers}
\appendtoks
% we need to reassign the number because new patterns can be defined later on
% so let's hope not that many \setups happen during a run
- \global\expandafter\let\csname\??languagenumbers\currentlanguage\endcsname\undefined
+ \expandafter\glet\csname\??languagenumbers\currentlanguage\endcsname\undefined
\to \everysetuplanguage
\def\lang_basics_synchronize_yes
@@ -471,7 +380,7 @@
\letvalue{\??languagenumbers}\lang_basics_synchronize_yes % runtime
\to \everydump
-\def\lang_basics_synchronize% assumes that \currentlanguage is set % % % use different name as complex
+\def\lang_basics_synchronize
{\normallanguage\csname\??languagenumbers
\ifcsname\??languagenumbers\currentlanguage\endcsname
\currentlanguage
@@ -481,12 +390,7 @@
\the\everylanguage
\relax}
-% experimental
-
\newcount\hyphenstate
-
-% so far
-
\newcount\hyphenminoffset
\unexpanded\def\lesshyphens
@@ -530,7 +434,7 @@
% \setups[\languageparameter\c!setups]%
% \to \everylanguage
-%D You can setup the 'default' language to reset settings.
+%D You can setup the default language to reset settings.
\appendtoks
\edef\currentlanguagesetups{\languageparameter\c!setups}%
@@ -548,7 +452,12 @@
% this will move to core-spa !
\appendtoks
- \doifelse{\languageparameter\c!spacing}\v!broad\nonfrenchspacing\frenchspacing
+ \edef\p_spacing{\languageparameter\c!spacing}%
+ \ifx\p_spacing\v!broad
+ \nonfrenchspacing
+ \else
+ \frenchspacing
+ \fi
\to \everylanguage
% \mainlanguage[nl] \setuplanguage[nl][lefthyphen=,righthyphen=?]
@@ -576,11 +485,6 @@
\fi
\to \everylanguage
-% The following may be a solution for the fact that one cannot
-% change catcodes of characters like : and ; inside an environment.
-
-% we will also permit access by the other names
-
%D Fast switcher
\def\lang_basics_switch_asked
@@ -613,23 +517,13 @@
\newcount\mainlanguagenumber
-% \unexpanded\def\mainlanguage[#1]%
-% {\edef\askedlanguage{#1}%
-% \ifx\askedlanguage\empty \else
-% \ifcsname\??languagelinked\askedlanguage\endcsname
-% \edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
-% \ifx\currentlanguage\askedlanguage
-% \ifx\currentmainlanguage\askedlanguage \else
-% \setcurrentlanguage\askedlanguage\askedlanguage
-% \lang_basics_synchronize
-% \fi
-% \else
-% \setcurrentlanguage\askedlanguage\askedlanguage
-% \lang_basics_synchronize
-% \fi
-% \fi
-% \fi
-% \mainlanguagenumber\normallanguage}
+%D Beware: you might need to use \type {\dontleavehmode} outside and|/|or \type {\par}
+%D inside the group!
+
+\unexpanded\def\startlanguage
+ {\begingroup\language}
+
+\let\stoplanguage\endgroup
\unexpanded\def\mainlanguage[#1]%
{\edef\askedlanguage{#1}%
@@ -662,9 +556,8 @@
\def\splitsymbol#1%
{\splitsequence{#1}{\languageparameter\c!limittext}}
-%D Just like with subsentence boundary symbols, quotes
-%D placement depends on the current language, therefore we show
-%D the defaults here.
+%D Just like with subsentence boundary symbols, quotes placement depends on the
+%D current language, therefore we show the defaults here.
%D
%D \def\ShowLanguageValues [#1] [#2] #3 #4
%D {\blank
@@ -686,6 +579,7 @@
%D \ShowLanguageValues [da] [danish] deense ...
%D \ShowLanguageValues [de] [german] duitse degelijkheid
%D \ShowLanguageValues [en] [english] engelse humor
+%D \ShowLanguageValues [et] [estonian] ...
%D \ShowLanguageValues [fi] [finnish] finse ...
%D \ShowLanguageValues [fr] [french] franse slag
%D \ShowLanguageValues [it] [italian] italiaanse ...
@@ -699,10 +593,9 @@
%D \ShowLanguageValues [sv] [swedish] zweedse ...
%D \ShowLanguageValues [tr] [turkish] turks fruit
-%D We support a lot of languages. These are specified and
-%D loaded in separate files, according to their roots. Here
-%D we only take care of (postponed) setting of the current
-%D language.
+%D We support a lot of languages. These are specified and loaded in separate files,
+%D according to their roots. Here we only take care of (postponed) setting of the
+%D current language.
%D
%D \unprotect
%D \placetable{The germanic languages (\type{lang-ger})}
@@ -773,9 +666,8 @@
\unexpanded\def\nopatterns{\normallanguage\minusone}
-%D We default to the language belonging to the interface. This
-%D is one of the few places outside the interface modules where
-%D \type{\startinterface} is used.
+%D We default to the language belonging to the interface. This is one of the few
+%D places outside the interface modules where \type {\startinterface} is used.
\setupcurrentlanguage[\s!en]
diff --git a/tex/context/base/mkiv/lang-lab.mkiv b/tex/context/base/mkiv/lang-lab.mkiv
index 73637753d..9d73d96e5 100644
--- a/tex/context/base/mkiv/lang-lab.mkiv
+++ b/tex/context/base/mkiv/lang-lab.mkiv
@@ -277,10 +277,16 @@
\def\lang_labels_text_prefix_copy_pair[#1=#2]%
{\lang_labels_text_prefix_copy_pair_indeed{#1}[#2,,]}
+% \def\lang_labels_text_prefix_copy_pair_indeed#1[#2,#3]%
+% {\expandafter\let
+% \csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\expandafter\endcsname
+% \csname\??label\currenttextprefixclass:\currenttextprefixtag:#2\endcsname}
+%
+% this delays the aliasing so that we can switch maillanguage in between
+
\def\lang_labels_text_prefix_copy_pair_indeed#1[#2,#3]%
- {\expandafter\let
- \csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\expandafter\endcsname
- \csname\??label\currenttextprefixclass:\currenttextprefixtag:#2\endcsname}
+ {\expandafter\edef\csname\??label\currenttextprefixclass:#1\endcsname
+ {{\noexpand\csname\??label\currenttextprefixclass:\noexpand\reallanguagetag\noexpand\currentmainlanguage:#2\endcsname}{}}}
\definelabelclass [head] [0] % titles
\definelabelclass [label] [0] % texts
diff --git a/tex/context/base/mkiv/lang-mis.mkiv b/tex/context/base/mkiv/lang-mis.mkiv
index eb7dc7d80..3ec29a782 100644
--- a/tex/context/base/mkiv/lang-mis.mkiv
+++ b/tex/context/base/mkiv/lang-mis.mkiv
@@ -145,7 +145,11 @@
%D modules these can be tuned by a setup command. Watch the (maybe) better looking
%D compound hyphen.
-\ifx\compoundhyphen \undefined \unexpanded\def\compoundhyphen {\hbox{-\kern-.25ex-}} \fi
+% hm why ex
+
+\ifx\compoundhyphen \undefined
+ \unexpanded\def\compoundhyphen {\hbox{-\kern-.10775\emwidth-}} % .25\exheight
+\fi
%D The last two variables are needed for subsentences |<|like this one|>| which we
%D did not yet mention. We want to enable breaking but at the same time don't want
@@ -156,7 +160,8 @@
\ifx\postwordbreak\undefined \unexpanded\def\postwordbreak {\penalty\zerocount \hskip\zeropoint\relax} \fi
\ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667\emwidth} \fi % language specific
-\unexpanded\def\permithyphenation{\ifhmode\prewordbreak\fi} % doesn't remove spaces
+%unexpanded\def\permithyphenation{\ifhmode\prewordbreak\fi} % doesn't remove spaces
+\unexpanded\def\permithyphenation{\ifhmode\wordboundary\fi} % doesn't remove spaces
%D \macros
%D {beginofsubsentence,endofsubsentence,
@@ -202,22 +207,21 @@
\setnewconstant\discretionarymode\plusone
-\unexpanded\def\ignorediscretionaries
- {\discretionarymode\zerocount}
+\unexpanded\def\ignorediscretionaries{\discretionarymode\zerocount}
+\unexpanded\def\obeydiscretionaries {\discretionarymode\plusone}
\def\lang_discretionaries_command
{% if direct if, we need \relax for lookahead in math mode
\csname\??discretionarymode
\ifcase\discretionarymode
- n% \csstring\lang_discretionaries_process_none
+ n%
\else\ifmmode
- m% \csstring\lang_discretionaries_process_math
+ m%
\else
- t% \csstring\lang_discretionaries_process_text
+ t%
\fi\fi
\endcsname}
-% \def\lang_discretionaries_process_none#1%
\setvalue{\??discretionarymode n}#1%
{\detokenize{#1}}
@@ -230,19 +234,22 @@
\newconditional\punctafterdiscretionary
\newconditional\spaceafterdiscretionary
-\def\lang_discretionaries_check_before
+\def\lang_discretionaries_check_before %i sused grouped
{\ifvmode
\dontleavehmode
\fi
\ifhmode
- \begingroup
- \setbox\scratchbox\lastbox
- \ifzeropt\wd\scratchbox
- \let\postwordbreak\prewordbreak
- \fi
- \box\scratchbox\relax
- \endgroup
- \fi}
+ %\begingroup
+ %\setbox\scratchbox\lastbox
+ %\ifzeropt\wd\scratchbox
+ % \box\scratchbox\relax
+ % \endgroup
+ % \let\postwordbreak\prewordbreak
+ %\else
+ % \box\scratchbox\relax
+ % \endgroup
+ %\fi
+ \fi}
\def\lang_discretionaries_check_after
{\setfalse\punctafterdiscretionary
@@ -254,10 +261,8 @@
\ifx :\nextnext \settrue \punctafterdiscretionary \else
\ifx ;\nextnext \settrue \punctafterdiscretionary \fi\fi\fi\fi\fi\fi}
-%let\lang_discretionaries_process_math\handlemathmodediscretionary
\letvalue{\??discretionarymode m}\handlemathmodediscretionary
-% \def\lang_discretionaries_process_text#1% grouped !
\setvalue{\??discretionarymode t}#1%
{\bgroup
\let\nextnextnext\egroup
@@ -278,39 +283,47 @@
\ifcsname\??discretionaryaction\string#1\endcsname
\lastnamedcs
\else\ifconditional\spaceafterdiscretionary
- \prewordbreak\hbox{\string#1}\relax
+ %\prewordbreak\hbox{\string#1}\relax
+ \wordboundary\hbox{\string#1}\relax
\else\ifconditional\punctafterdiscretionary
- \prewordbreak\hbox{\string#1}\relax
+ %\prewordbreak\hbox{\string#1}\relax
+ \wordboundary\hbox{\string#1}\wordboundary
\else
- \prewordbreak\hbox{\string#1}\prewordbreak
+ %\prewordbreak\hbox{\string#1}\prewordbreak
+ \wordboundary\hbox{\string#1}\wordboundary
\fi\fi\fi
\def\nextnextnext{\afterassignment\egroup\let\next=}%
\else
\lang_discretionaries_check_before
% the next line has been changed (20050203)
- % \prewordbreak\hbox{\textmodediscretionary\nextnext}\allowbreak\postwordbreak
+ % \prewordbreak\hbox{\textmodediscretionary\nextnext}\postwordbreak
% but an hbox blocks a possible \discretionary
\ifcsname\??discretionaryaction\endcsname
\lastnamedcs
\else\ifconditional\spaceafterdiscretionary
- \prewordbreak\textmodediscretionary\relax
+ %\prewordbreak\textmodediscretionary\relax
+ \wordboundary\textmodediscretionary\relax
\else\ifconditional\punctafterdiscretionary
- \prewordbreak\textmodediscretionary\relax
+ %\prewordbreak\textmodediscretionary\relax
+ \wordboundary\textmodediscretionary\relax
\else
- \prewordbreak\textmodediscretionary\prewordbreak
+ %\prewordbreak\textmodediscretionary\prewordbreak
+ \wordboundary\textmodediscretionary\wordboundary
\fi\fi\fi
- % \prewordbreak\textmodediscretionary\nextnext\allowbreak\postwordbreak
\fi
\else\ifcsname\??discretionaryaction\discretionarytoken\endcsname
\lastnamedcs
\else
\lang_discretionaries_check_before
\ifconditional\spaceafterdiscretionary
- \prewordbreak\hbox{#2}\relax
+ %\prewordbreak\hbox{#2}\relax
+ \wordboundary\hbox{#2}\relax
\else\ifconditional\punctafterdiscretionary
- \prewordbreak\hbox{#2}\relax
+ %\prewordbreak\hbox{#2}\relax
+ \wordboundary\hbox{#2}\relax
\else
- \prewordbreak\discretionary{\hbox{#2}}{}{\hbox{#2}}\allowbreak\postwordbreak
+ %\prewordbreak\discretionary{\hbox{#2}}{}{\hbox{#2}}\postwordbreak
+ \wordboundary\discretionary{\hbox{#2}}{}{\hbox{#2}}\wordboundary
\fi\fi
\fi\fi
\nextnextnext}
@@ -324,35 +337,33 @@
\unexpanded\def\directdiscretionary
{\csname\??discretionarymode
\ifcase\discretionarymode
- n% \csstring\lang_discretionaries_process_none
+ n%
\else
- d% \csstring\lang_discretionaries_process_direct
+ d%
\fi
\endcsname}
\unexpanded\def\indirectdiscretionary
{\csname\??discretionarymode
\ifcase\discretionarymode
- n% \csstring\lang_discretionaries_process_none
+ n%
\else
- i% \csstring\lang_discretionaries_process_indirect
+ i%
\fi
\endcsname}
-% \unexpanded\def\lang_discretionaries_process_direct#1%
\setuvalue{\??discretionarymode d}#1%
{\edef\discretionarytoken{\detokenize{#1}}%
\let\textmodediscretionary\compoundhyphen
- %\executeifdefined{\??discretionaryaction\discretionarytoken}{\indirectdiscretionary{#1}}}
\ifcsname\??discretionaryaction\discretionarytoken\endcsname
\expandafter\lastnamedcs
\else
\expandafter\indirectdiscretionary
\fi{#1}}
-% \unexpanded\unexpanded\def\lang_discretionaries_process_indirect#1%
\setuvalue{\??discretionarymode i}#1%
- {\prewordbreak\discretionary{\hbox{#1}}{}{\hbox{#1}}\allowbreak\postwordbreak}
+ %{\prewordbreak\discretionary{\hbox{#1}}{}{\hbox{#1}}\postwordbreak}
+ {\wordboundary\discretionary{\hbox{#1}}{}{\hbox{#1}}\wordboundary}
\unexpanded\def\definetextmodediscretionary #1
{\setvalue{\??discretionaryaction\detokenize{#1}}}
@@ -376,11 +387,14 @@
\def\lang_discretionaries_hyphen_like#1#2%
{\ifconditional\spaceafterdiscretionary
- \prewordbreak\hbox{#1}\relax
+ %prewordbreak\hbox{#1}\relax
+ \wordboundary\hbox{#1}\relax
\else\ifconditional\punctafterdiscretionary
- \prewordbreak\hbox{#1}\relax
+ %prewordbreak\hbox{#1}\relax
+ \wordboundary\hbox{#1}\relax
\else
- \prewordbreak#2\postwordbreak % was prewordbreak
+ %\prewordbreak#2\postwordbreak % was prewordbreak
+ \wordboundary#2\wordboundary
\fi\fi}
\definetextmodediscretionary {}
@@ -397,59 +411,65 @@
\definetextmodediscretionary (
{\ifdim\lastskip>\zeropoint
- (\prewordbreak
+ %(\prewordbreak
+ (\wordboundary
\else
- \prewordbreak\discretionary{}{(-}{(}\prewordbreak
+ %\prewordbreak\discretionary{}{(-}{(}\prewordbreak
+ \wordboundary\discretionary{}{(-}{(}\wordboundary
\fi}
\definetextmodediscretionary ~
- {\prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak}
+ %{\prewordbreak\discretionary{-}{}{\thinspace}\postwordbreak}
+ {\wordboundary\discretionary{-}{}{\thinspace}\wordboundary}
\definetextmodediscretionary '
- {\prewordbreak\discretionary{-}{}{'}\postwordbreak}
+ %{\prewordbreak\discretionary{-}{}{'}\postwordbreak}
+ {\wordboundary\discretionary{-}{}{'}\wordboundary}
\definetextmodediscretionary ^
- {\prewordbreak\discretionary{\hbox{\normalstartimath|\normalstopimath}}{}{\hbox{\normalstartimath|\normalstopimath}}%
- \allowbreak\postwordbreak} % bugged
-
-% \definetextmodediscretionary <
-% {\beginofsubsentence\prewordbreak\beginofsubsentencespacing}
-%
-% \definetextmodediscretionary >
-% {\endofsubsentencespacing\prewordbreak\endofsubsentence}
-%
-% \definetextmodediscretionary =
-% {\prewordbreak\midsentence\prewordbreak}
+ %{\prewordbreak\discretionary{\hbox{\normalstartimath|\normalstopimath}}{}{\hbox{\normalstartimath|\normalstopimath}}%
+ % \postwordbreak} % bugged
+ {\wordboundary\discretionary{\hbox{\normalstartimath|\normalstopimath}}{}{\hbox{\normalstartimath|\normalstopimath}}%
+ \wordboundary} % bugged
\definetextmodediscretionary <
- {\beginofsubsentence\prewordbreak\beginofsubsentencespacing
+ %{\beginofsubsentence\prewordbreak\beginofsubsentencespacing
+ {\beginofsubsentence\wordboundary\beginofsubsentencespacing
\aftergroup\ignorespaces} % tricky, we need to go over the \nextnextnext
\definetextmodediscretionary >
{\removeunwantedspaces
- \endofsubsentencespacing\prewordbreak\endofsubsentence}
+ %\endofsubsentencespacing\prewordbreak\endofsubsentence}
+ \endofsubsentencespacing\wordboundary\endofsubsentence}
\definetextmodediscretionary =
{\removeunwantedspaces
- \prewordbreak\midsentence\prewordbreak
+ %\prewordbreak\midsentence\prewordbreak
+ \wordboundary\midsentence\wordboundary
\aftergroup\ignorespaces}
% french
-\definetextmodediscretionary : {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{:}:}
-\definetextmodediscretionary ; {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{;};}
-\definetextmodediscretionary ? {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{?}?}
-\definetextmodediscretionary ! {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{!}!}
+%definetextmodediscretionary : {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{:}:}
+%definetextmodediscretionary ; {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{;};}
+%definetextmodediscretionary ? {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{?}?}
+%definetextmodediscretionary ! {\removeunwantedspaces\prewordbreak\kern\hspaceamount\empty{!}!}
+
+\definetextmodediscretionary : {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{:}:}
+\definetextmodediscretionary ; {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{;};}
+\definetextmodediscretionary ? {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{?}?}
+\definetextmodediscretionary ! {\removeunwantedspaces\wordboundary\kern\hspaceamount\empty{!}!}
-\definetextmodediscretionary *
- {\prewordbreak\discretionary{-}{}{\kern.05em}\prewordbreak}
+%definetextmodediscretionary * {\prewordbreak\discretionary{-}{}{\kern.05\emwidth}\prewordbreak}
+\definetextmodediscretionary * {\wordboundary\discretionary{-}{}{\kern.05\emwidth}\wordboundary}
% spanish
-\definetextmodediscretionary ?? {\prewordbreak\questiondown}
-\definetextmodediscretionary !! {\prewordbreak\exclamdown}
+%definetextmodediscretionary ?? {\prewordbreak\questiondown}
+%definetextmodediscretionary !! {\prewordbreak\exclamdown}
-% \ifx\normalcompound\undefined \let\normalcompound=| \fi
+\definetextmodediscretionary ?? {\wordboundary\questiondown}
+\definetextmodediscretionary !! {\wordboundary\exclamdown}
%D \installdiscretionary | +
%D \installdiscretionary + =
diff --git a/tex/context/base/mkiv/lang-rep.lua b/tex/context/base/mkiv/lang-rep.lua
index a5c4d97c8..93509d82a 100644
--- a/tex/context/base/mkiv/lang-rep.lua
+++ b/tex/context/base/mkiv/lang-rep.lua
@@ -42,8 +42,6 @@ local report_replacement = logs.reporter("languages","replacements")
local glyph_code = nodes.nodecodes.glyph
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local getnext = nuts.getnext
local getprev = nuts.getprev
@@ -217,9 +215,7 @@ local function tonodes(list,template)
end
function replacements.handler(head)
- head = tonut(head)
local current = head
- local done = false
local overload = attributes.applyoverloads
while current do
if getid(current) == glyph_code then
@@ -327,14 +323,13 @@ function replacements.handler(head)
if overload then
overload(final,getnext(precurrent),getprev(current))
end
- done = true
end
end
end
-- we're one ahead now but we need to because we handle words
current = getnext(current)
end
- return tonode(head), done
+ return head
end
local enabled = false
diff --git a/tex/context/base/mkiv/lang-spa.mkiv b/tex/context/base/mkiv/lang-spa.mkiv
index e7cb0025f..7109ad051 100644
--- a/tex/context/base/mkiv/lang-spa.mkiv
+++ b/tex/context/base/mkiv/lang-spa.mkiv
@@ -41,17 +41,15 @@
%D Alternative discretionary handlers:
-\definetextmodediscretionary :
- {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{:}:}
+%definetextmodediscretionary : {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{:}:}
+%definetextmodediscretionary ; {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{;};}
+%definetextmodediscretionary ? {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{?}?}
+%definetextmodediscretionary ! {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{!}!}
-\definetextmodediscretionary ;
- {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{;};}
-
-\definetextmodediscretionary ?
- {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{?}?}
-
-\definetextmodediscretionary !
- {\removeunwantedspaces\prewordbreak\kern\hspaceamount\currentlanguage{!}!}
+\definetextmodediscretionary : {\removeunwantedspaces\wordboundary\kern\hspaceamount\currentlanguage{:}:}
+\definetextmodediscretionary ; {\removeunwantedspaces\wordboundary\kern\hspaceamount\currentlanguage{;};}
+\definetextmodediscretionary ? {\removeunwantedspaces\wordboundary\kern\hspaceamount\currentlanguage{?}?}
+\definetextmodediscretionary ! {\removeunwantedspaces\wordboundary\kern\hspaceamount\currentlanguage{!}!}
%D \startbuffer
%D \mainlanguage[en] \quotation{test \quotation{test} test}\par
diff --git a/tex/context/base/mkiv/lang-txt.lua b/tex/context/base/mkiv/lang-txt.lua
index b1f50bc80..d287f7e6d 100644
--- a/tex/context/base/mkiv/lang-txt.lua
+++ b/tex/context/base/mkiv/lang-txt.lua
@@ -25,6 +25,7 @@ if not modules then modules = { } end modules ['lang-txt'] = {
-- de German Tobias Burnus, ...
-- en English Hans Hagen, ...
-- es Spanish Andrés Montoya, ...
+-- et Estonian Clyde Johnston
-- fi Finish ...
-- fr French Daniel Flipo, Arthur Reutenauer
-- gr Greek Apostolos Syropoulos, Thomas Schmitz
@@ -86,6 +87,7 @@ data.labels={
["labels"]={
["de"]="Band",
["en"]="Volume",
+ ["et"]="Köide",
["nl"]="Deel",
["pe"]="جلد",
},
@@ -95,6 +97,7 @@ data.labels={
["de"]="und",
["en"]="and",
["es"]="y",
+ ["et"]="ja",
["fr"]="et",
["it"]="e",
["nl"]="en",
@@ -106,6 +109,7 @@ data.labels={
["de"]="Auflage",
["en"]="edition",
["es"]="edición",
+ ["et"]="väljaanne",
["fr"]="édition",
["it"]="edizione",
["nl"]="editie",
@@ -116,6 +120,7 @@ data.labels={
["labels"]={
["de"]="Herausgeber",
["en"]="editor",
+ ["et"]="toimetaja",
["fr"]="éditeur",
["it"]="a cura di",
["pe"]="ویراستار",
@@ -126,6 +131,7 @@ data.labels={
["de"]="Herausgeber",
["en"]="editors",
["es"]="editores",
+ ["et"]="toimetajad",
["fr"]="éditeurs",
["it"]="a cura di",
},
@@ -143,6 +149,7 @@ data.labels={
["de"]="Masterarbeit",
["en"]="Master's thesis",
["es"]="Tesis de maestría",
+ ["et"]="magistritöö",
["fr"]="Thèse de master (DEA, DESS, master)",
["it"]="Tesi di laurea",
["nl"]="Masterproef",
@@ -169,12 +176,14 @@ data.labels={
["others"]={
["labels"]={
["en"]="et al.",
+ ["et"]="jt",
},
},
["p"]={
["labels"]={
["de"]="S.",
["en"]="p.",
+ ["et"]="lk",
["pe"]="ص",
},
},
@@ -182,6 +191,7 @@ data.labels={
["labels"]={
["de"]="Seiten",
["en"]="pages",
+ ["et"]="leheküljed",
["nl"]="paginas",
["pe"]="صفحات",
},
@@ -191,6 +201,7 @@ data.labels={
["de"]="Patent",
["en"]="Patent",
["es"]="Patente",
+ ["et"]="Patent",
["fr"]="Brevet",
["it"]="Brevetto",
["nl"]="Octrooi",
@@ -201,6 +212,7 @@ data.labels={
["de"]="Dissertation",
["en"]="PhD thesis",
["es"]="Tesis doctoral",
+ ["et"]="doktoritöö",
["fr"]="Thèse de doctorat",
["it"]="Tesi di dottorato",
["nl"]="Proefschrift",
@@ -211,6 +223,7 @@ data.labels={
["labels"]={
["de"]="S.",
["en"]="pp.",
+ ["et"]="lk-d",
["pe"]="صص",
},
},
@@ -219,6 +232,7 @@ data.labels={
["de"]="Technischer Bericht",
["en"]="Technical report",
["es"]="Informe técnico",
+ ["et"]="tehniline raport",
["fr"]="Rapport technique",
["it"]="Relazione tecnica",
["nl"]="Technisch rapport",
@@ -229,6 +243,7 @@ data.labels={
["labels"]={
["de"]="Band",
["en"]="volume",
+ ["et"]="köide",
["nl"]="deel",
["pe"]="جلد",
},
@@ -238,6 +253,7 @@ data.labels={
["de"]="mit",
["en"]="with",
["es"]="con",
+ ["et"]="koos",
["fr"]="avec",
["it"]="con",
["nl"]="met",
@@ -615,28 +631,29 @@ data.labels={
["labels"]={
["af"]="",
["ca"]="",
- ["cs"]="a",
+ ["cs"]=" a ",
["da"]="",
- ["de"]="und",
- ["en"]="and",
- ["es"]="y",
+ ["de"]=" und ",
+ ["en"]=" and ",
+ ["es"]=" y ",
+ ["et"]=" ja ",
["fi"]="",
["fr"]="",
["gr"]="",
- ["hr"]="i",
- ["hu"]="és",
+ ["hr"]=" i ",
+ ["hu"]=" és ",
["it"]="",
["la"]="",
["lt"]="",
["nb"]="",
- ["nl"]="en",
+ ["nl"]=" en ",
["nn"]="",
- ["pe"]="و",
- ["pl"]="i",
+ ["pe"]=" و ",
+ ["pl"]=" i ",
["pt"]="",
["ro"]="",
["ru"]="",
- ["sk"]="a",
+ ["sk"]=" a ",
["sl"]="",
["sv"]="",
["tk"]="",
@@ -657,6 +674,7 @@ data.labels={
["de"]="Anhang ",
["en"]="Appendix ",
["es"]="Apéndice ",
+ ["et"]="Lisa ",
["fi"]="",
["fr"]="Annexe ",
["gr"]="Παράρτημα",
@@ -697,6 +715,7 @@ data.labels={
["de"]="April",
["en"]="April",
["es"]="abril",
+ ["et"]="aprill",
["fi"]="huhtikuu",
["fr"]="avril",
["gr"]="Απρίλιος",
@@ -739,6 +758,7 @@ data.labels={
["de"]="",
["en"]="apr",
["es"]="abr.",
+ ["et"]="apr",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -773,6 +793,7 @@ data.labels={
["de"]="auf Seite ",
["en"]="at page ",
["es"]="en la página ",
+ ["et"]="leheküljel ",
["fi"]="",
["fr"]="à la page ",
["gr"]="",
@@ -812,6 +833,7 @@ data.labels={
["de"]="August",
["en"]="August",
["es"]="agosto",
+ ["et"]="august",
["fi"]="elokuu",
["fr"]="août",
["gr"]="Αύγουστος",
@@ -854,6 +876,7 @@ data.labels={
["de"]="",
["en"]="aug",
["es"]="ago.",
+ ["et"]="aug",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -890,6 +913,7 @@ data.labels={
["de"]="Kapitel ",
["en"]="Chapter ",
["es"]="Capítulo ",
+ ["et"]="Peatükk ",
["fi"]="",
["fr"]="Chapitre ",
["gr"]="Κεφάλαιο",
@@ -926,6 +950,7 @@ data.labels={
["de"]="",
["en"]=" (continued)",
["es"]=" (continúa)",
+ ["et"]=" (jätkub)",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -954,6 +979,7 @@ data.labels={
["day"]={
["labels"]={
["en"]="day",
+ ["et"]="päev",
["kr"]="일",
["nl"]="dag",
["pe"]="روز",
@@ -972,6 +998,7 @@ data.labels={
["de"]="Dezember",
["en"]="December",
["es"]="diciembre",
+ ["et"]="detsember",
["fi"]="joulukuu",
["fr"]="décembre",
["gr"]="Δεκέμβριος",
@@ -1014,6 +1041,7 @@ data.labels={
["de"]="",
["en"]="dec",
["es"]="dic.",
+ ["et"]="dets",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -1051,6 +1079,7 @@ data.labels={
["de"]="Februar",
["en"]="February",
["es"]="febrero",
+ ["et"]="veebruar",
["fi"]="helmikuu",
["fr"]="février",
["gr"]="Φεβρουάριος",
@@ -1093,6 +1122,7 @@ data.labels={
["de"]="",
["en"]="feb",
["es"]="feb.",
+ ["et"]="veebr",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -1128,6 +1158,7 @@ data.labels={
["de"]="Abbildung ",
["en"]="Figure ",
["es"]="Figura ",
+ ["et"]="Joonis ",
["fi"]="Kuva ",
["fr"]="Figure ",
["gr"]="Σχήμα",
@@ -1158,6 +1189,7 @@ data.labels={
["followingpage"]={
["labels"]={
["en"]="on a following page",
+ ["et"]="järgmisel leheküljel",
["nl"]="op een volgende bladzijde",
["pe"]="در صفحات آینده",
},
@@ -1173,6 +1205,7 @@ data.labels={
["de"]="Freitag",
["en"]="Friday",
["es"]="viernes",
+ ["et"]="reede",
["fi"]="perjantai",
["fr"]="vendredi",
["gr"]="Παρασκευή",
@@ -1211,6 +1244,7 @@ data.labels={
["de"]="Graphik ",
["en"]="Graphic ",
["es"]="Gráfico ",
+ ["et"]="Pilt ",
["fi"]="Grafiikka ",
["fr"]="Illustration ",
["gr"]="Γραφικό",
@@ -1247,6 +1281,7 @@ data.labels={
["de"]="siehe oben",
["en"]="as we show above",
["es"]="como se muestra arriba",
+ ["et"]="nii nagu üleval näidatud",
["fi"]="",
["fr"]="ci-dessus",
["gr"]="",
@@ -1283,6 +1318,7 @@ data.labels={
["de"]="siehe unten",
["en"]="as we show below",
["es"]="como se muestra abajo",
+ ["et"]="nii nagu all näidatud",
["fi"]="",
["fr"]="ci-dessous",
["gr"]="",
@@ -1320,6 +1356,7 @@ data.labels={
["de"]="Intermezzo ",
["en"]="Intermezzo ",
["es"]="Intermedio ",
+ ["et"]="Vahemäng ",
["fi"]="Intermezzo ",
["fr"]="Intermède ",
["gr"]="Παύση",
@@ -1359,6 +1396,7 @@ data.labels={
["de"]="Januar",
["en"]="January",
["es"]="enero",
+ ["et"]="jaanuar",
["fi"]="tammikuu",
["fr"]="janvier",
["gr"]="Ιανουάριος",
@@ -1401,6 +1439,7 @@ data.labels={
["de"]="",
["en"]="jan",
["es"]="ene.",
+ ["et"]="jaan",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -1439,6 +1478,7 @@ data.labels={
["de"]="Juli",
["en"]="July",
["es"]="julio",
+ ["et"]="juuli",
["fi"]="heinäkuu",
["fr"]="juillet",
["gr"]="Ιούλιος",
@@ -1481,6 +1521,7 @@ data.labels={
["de"]="",
["en"]="jul",
["es"]="jul.",
+ ["et"]="juuli",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -1518,6 +1559,7 @@ data.labels={
["de"]="Juni",
["en"]="June",
["es"]="junio",
+ ["et"]="juuni",
["fi"]="kesäkuu",
["fr"]="juin",
["gr"]="Ιούνιος",
@@ -1560,6 +1602,7 @@ data.labels={
["de"]="",
["en"]="jun",
["es"]="jun.",
+ ["et"]="juuni",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -1595,6 +1638,7 @@ data.labels={
["de"]="Zeile ",
["en"]="line ",
["es"]="línea ",
+ ["et"]="joon ",
["fi"]="rivi ",
["fr"]="ligne ",
["gr"]="Γραμμή",
@@ -1633,6 +1677,7 @@ data.labels={
["de"]="Zeilen ",
["en"]="lines ",
["es"]="líneas ",
+ ["et"]="jooned ",
["fi"]="rivie ",
["fr"]="lignes ",
["gr"]="Γραμμές",
@@ -1672,6 +1717,7 @@ data.labels={
["de"]="März",
["en"]="March",
["es"]="marzo",
+ ["et"]="märts",
["fi"]="maaliskuu",
["fr"]="mars",
["gr"]="Μάρτιος",
@@ -1714,6 +1760,7 @@ data.labels={
["de"]="",
["en"]="mar",
["es"]="mar.",
+ ["et"]="märts",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -1752,6 +1799,7 @@ data.labels={
["de"]="Mai",
["en"]="May",
["es"]="mayo",
+ ["et"]="mai",
["fi"]="toukokuu",
["fr"]="mai",
["gr"]="Μάιος",
@@ -1794,6 +1842,7 @@ data.labels={
["de"]="",
["en"]="may",
["es"]="may.",
+ ["et"]="mai",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -1829,6 +1878,7 @@ data.labels={
["de"]="Montag",
["en"]="Monday",
["es"]="lunes",
+ ["et"]="esmaspäev",
["fi"]="maanantai",
["fr"]="lundi",
["gr"]="Δευτέρα",
@@ -1859,6 +1909,7 @@ data.labels={
["month"]={
["labels"]={
["en"]="month",
+ ["et"]="kuu",
["kr"]="월",
["nl"]="maand",
["pe"]="ماه",
@@ -1877,6 +1928,7 @@ data.labels={
["de"]="November",
["en"]="November",
["es"]="noviembre",
+ ["et"]="november",
["fi"]="marraskuu",
["fr"]="novembre",
["gr"]="Νοέμβριος",
@@ -1919,6 +1971,7 @@ data.labels={
["de"]="",
["en"]="nov",
["es"]="nov.",
+ ["et"]="nov",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -1955,6 +2008,7 @@ data.labels={
["de"]="Oktober",
["en"]="October",
["es"]="octubre",
+ ["et"]="oktoober",
["fi"]="lokakuu",
["fr"]="octobre",
["gr"]="Οκτώβριος",
@@ -1997,6 +2051,7 @@ data.labels={
["de"]="",
["en"]="oct",
["es"]="oct.",
+ ["et"]="okt",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -2031,6 +2086,7 @@ data.labels={
["de"]="Seite ",
["en"]="page ",
["es"]="página ",
+ ["et"]="lehekülg ",
["fi"]="",
["fr"]="page ",
["gr"]="",
@@ -2068,6 +2124,7 @@ data.labels={
["de"]="Teil ",
["en"]="Part ",
["es"]="Parte ",
+ ["et"]="Osa ",
["fi"]="Osa ",
["fr"]="Partie ",
["gr"]="Μέρος",
@@ -2098,6 +2155,7 @@ data.labels={
["precedingpage"]={
["labels"]={
["en"]="on a preceding page",
+ ["et"]="eelmisel lehel",
["nl"]="op een voorgaande bladzijde",
["pe"]="در صفحات گذشته",
},
@@ -2113,6 +2171,7 @@ data.labels={
["de"]="Samstag",
["en"]="Saturday",
["es"]="sábado",
+ ["et"]="laupäev",
["fi"]="lauantai",
["fr"]="samedi",
["gr"]="Σάββατο",
@@ -2152,6 +2211,7 @@ data.labels={
["de"]="",
["en"]="",
["es"]="Sección ",
+ ["et"]="jaos ",
["fi"]="",
["fr"]="Section ",
["gr"]="Ενότητα",
@@ -2189,6 +2249,7 @@ data.labels={
["de"]="siehe ",
["en"]="see ",
["es"]="ver: ",
+ ["et"]="vaadake ",
["fi"]="",
["fr"]="cf. ",
["gr"]="",
@@ -2228,6 +2289,7 @@ data.labels={
["de"]="September",
["en"]="September",
["es"]="septiembre",
+ ["et"]="september",
["fi"]="syyskuu",
["fr"]="septembre",
["gr"]="Σεπτέμβριος",
@@ -2270,6 +2332,7 @@ data.labels={
["de"]="",
["en"]="sep",
["es"]="sep.",
+ ["et"]="sept",
["fi"]="",
["fr"]="",
["gr"]="",
@@ -2306,6 +2369,7 @@ data.labels={
["de"]="",
["en"]="",
["es"]="Subsección ",
+ ["et"]="alajaotis ",
["fi"]="",
["fr"]="Soussection ",
["gr"]="Υπόενότητα",
@@ -2344,6 +2408,7 @@ data.labels={
["de"]="",
["en"]="",
["es"]="Subsubsección ",
+ ["et"]="alamjaotis ",
["fi"]="",
["fr"]="Soussoussection ",
["gr"]="",
@@ -2382,6 +2447,7 @@ data.labels={
["de"]="",
["en"]="",
["es"]="Subsubsubsección ",
+ ["et"]="",
["fi"]="",
["fr"]="Soussoussoussection ",
["gr"]="",
@@ -2419,6 +2485,7 @@ data.labels={
["de"]="Sonntag",
["en"]="Sunday",
["es"]="domingo",
+ ["et"]="pühapäev",
["fi"]="sunnuntai",
["fr"]="dimanche",
["gr"]="Κυριακή",
@@ -2457,6 +2524,7 @@ data.labels={
["de"]="Tabelle ",
["en"]="Table ",
["es"]="Tabla ",
+ ["et"]="Tabel ",
["fi"]="Taulukko ",
["fr"]="Tableau ",
["gr"]="Πίνακας",
@@ -2495,6 +2563,7 @@ data.labels={
["de"]="Donnerstag",
["en"]="Thursday",
["es"]="jueves",
+ ["et"]="neljapäev",
["fi"]="torstai",
["fr"]="jeudi",
["gr"]="Πέμπτη",
@@ -2533,6 +2602,7 @@ data.labels={
["de"]="Dienstag",
["en"]="Tuesday",
["es"]="martes",
+ ["et"]="teisipäev",
["fi"]="tiistai",
["fr"]="mardi",
["gr"]="Τρίτη",
@@ -2571,6 +2641,7 @@ data.labels={
["de"]="Mittwoch",
["en"]="Wednesday",
["es"]="miércoles",
+ ["et"]="kolmapäev",
["fi"]="keskiviikko",
["fr"]="mercredi",
["gr"]="Τετάρτη",
@@ -2601,6 +2672,7 @@ data.labels={
["year"]={
["labels"]={
["en"]="year",
+ ["et"]="aasta",
["kr"]="년",
["nl"]="jaar",
["pe"]="سال",
@@ -2619,6 +2691,7 @@ data.labels={
["de"]="Abkürzungen",
["en"]="Abbreviations",
["es"]="Abreviaturas",
+ ["et"]="Lühend",
["fi"]="Lyhennyksi",
["fr"]="Abréviations",
["gr"]="Συντομογραφίες",
@@ -2657,6 +2730,7 @@ data.labels={
["de"]="Inhalt",
["en"]="Contents",
["es"]="Contenido",
+ ["et"]="Sisu",
["fi"]="Sisällys",
["fr"]="Table des matières",
["gr"]="Περιεχόμενα",
@@ -2695,6 +2769,7 @@ data.labels={
["de"]="Abbildungen",
["en"]="Figures",
["es"]="Figuras",
+ ["et"]="Arvandmed",
["fi"]="Kuvi",
["fr"]="Figures",
["gr"]="Σχήματα",
@@ -2733,6 +2808,7 @@ data.labels={
["de"]="Graphiken",
["en"]="Graphics",
["es"]="Gráficos",
+ ["et"]="Graafika",
["fi"]="Grafiikkaoi",
["fr"]="Graphiques",
["gr"]="Γραφικά",
@@ -2771,6 +2847,7 @@ data.labels={
["de"]="Index",
["en"]="Index",
["es"]="Índice",
+ ["et"]="Indeks",
["fi"]="Indeksiluku",
["fr"]="Index",
["gr"]="Ευρετήριο",
@@ -2809,6 +2886,7 @@ data.labels={
["de"]="Intermezzi",
["en"]="Intermezzos",
["es"]="Intermedios",
+ ["et"]="Vahemängud",
["fi"]="Intermezzos",
["fr"]="Intermèdes",
["gr"]="Παύσεις",
@@ -2846,6 +2924,7 @@ data.labels={
["de"]="Logos",
["en"]="Logos",
["es"]="Logotipos",
+ ["et"]="Logos",
["fi"]="Vertauskuva",
["fr"]="Logos",
["gr"]="Λογότυπα",
@@ -2882,6 +2961,7 @@ data.labels={
["de"]="Literatur",
["en"]="References",
["es"]="Bibliografía",
+ ["et"]="Viited",
["fi"]="",
["fr"]="Bibliographie",
["gr"]="",
@@ -2919,6 +2999,7 @@ data.labels={
["de"]="Tabellen",
["en"]="Tables",
["es"]="Tablas",
+ ["et"]="Tabelid",
["fi"]="Taulukkoj",
["fr"]="Tableaux",
["gr"]="Πίνακες",
@@ -2957,6 +3038,7 @@ data.labels={
["de"]="Einheiten",
["en"]="Units",
["es"]="Unidades",
+ ["et"]="Ühikud",
["fi"]="Yksiköt",
["fr"]="Unités",
["gr"]="Μονάδες",
diff --git a/tex/context/base/mkiv/lang-url.lua b/tex/context/base/mkiv/lang-url.lua
index 95d959206..17ad15cd8 100644
--- a/tex/context/base/mkiv/lang-url.lua
+++ b/tex/context/base/mkiv/lang-url.lua
@@ -8,7 +8,6 @@ if not modules then modules = { } end modules ['lang-url'] = {
local utfcharacters, utfvalues, utfbyte, utfchar = utf.characters, utf.values, utf.byte, utf.char
local min, max = math.min, math.max
-local concat = table.concat
local context = context
@@ -77,9 +76,10 @@ urls.righthyphenmin = 3
urls.discretionary = nil
urls.packslashes = false
-directives.register("hyphenators.urls.packslashes",function(v)
- urls.packslashes = v
-end)
+directives.register("hyphenators.urls.packslashes",function(v) urls.packslashes = v end)
+
+local trace = false trackers.register("hyphenators.urls",function(v) trace = v end)
+local report = logs.reporter("hyphenators","urls")
-- local ctx_a = context.a
-- local ctx_b = context.b
@@ -153,8 +153,10 @@ local function action(hyphenatedurl,str,left,right,disc)
local pack = urls.packslashes
local length = 0
local list = utf.split(str)
+ local size = #list
+ local prev = nil
- for i=1,#list do
+ for i=1,size do
local what = nil
local dodi = false
local char = list[i]
@@ -162,7 +164,7 @@ local function action(hyphenatedurl,str,left,right,disc)
char = mapping[char] or char
if char == disc then
dodi = true
- elseif pack and char == "/" and list[i+1] == "/" then
+ elseif pack and char == "/" and (list[i+1] == "/" or prev == "/") then
what = "c"
else
local how = characters[char]
@@ -192,9 +194,13 @@ local function action(hyphenatedurl,str,left,right,disc)
else
list[i] = "\\" .. what .. "{" .. utfbyte(char) .. "}"
end
+ prev = char
+ end
+ if trace then
+ report("old : %s",str)
+ report("new : %t",list)
end
- list = concat(list)
- context(list)
+ context("%t",list)
end
-- urls.action = function(_,...) action(...) end -- sort of obsolete
diff --git a/tex/context/base/mkiv/lang-wrd.lua b/tex/context/base/mkiv/lang-wrd.lua
index 7363dbb31..9fbced2ce 100644
--- a/tex/context/base/mkiv/lang-wrd.lua
+++ b/tex/context/base/mkiv/lang-wrd.lua
@@ -31,7 +31,6 @@ local numbers = languages.numbers
local registered = languages.registered
local nuts = nodes.nuts
-local tonut = nuts.tonut
----- getfield = nuts.getfield
local getnext = nuts.getnext
@@ -43,8 +42,8 @@ local setattr = nuts.setattr
local getlang = nuts.getlang
local ischar = nuts.ischar
-local traverse_nodes = nuts.traverse
------ traverse_ids = nuts.traverse_id
+local nextnode = nuts.traversers.node
+----- nextglyph = nuts.traversers.glyph
local wordsdata = words.data
local chardata = characters.data
@@ -145,14 +144,13 @@ end
-- there is an n=1 problem somewhere in nested boxes
local function mark_words(head,whenfound) -- can be optimized and shared
- local current, language, done = tonut(head), nil, nil, 0, false
+ local current, language = head, nil, nil, 0
local str, s, nds, n = { }, 0, { }, 0 -- n could also be a table, saves calls
local function action()
if s > 0 then
local word = concat(str,"",1,s)
local mark = whenfound(language,word)
if mark then
- done = true
for i=1,n do
mark(nds[i])
end
@@ -198,7 +196,7 @@ local function mark_words(head,whenfound) -- can be optimized and shared
-- n = n + 1
-- nds[n] = current
-- --
- -- for current in traverse_ids(glyph_code,r) do
+ -- for current in nextglyph, r do
-- local code = getchar(current)
-- n = n + 1
-- nds[n] = current
@@ -217,7 +215,7 @@ local function mark_words(head,whenfound) -- can be optimized and shared
if s > 0 then
action()
end
- return head, done
+ return head
end
local methods = { }
@@ -285,7 +283,7 @@ local function sweep(language,str)
end
methods[1] = function(head)
- for n in traverse_nodes(head) do
+ for n in nextnode, head do
setattr(n,a_color,unsetvalue) -- hm, not that selective (reset color)
end
return mark_words(head,sweep)
@@ -380,7 +378,7 @@ local function sweep(language,str)
end
methods[3] = function(head)
- for n in traverse_nodes(head) do
+ for n in nextnode, head do
setattr(n,a_color,unsetvalue)
end
return mark_words(head,sweep)
diff --git a/tex/context/base/mkiv/lpdf-ano.lua b/tex/context/base/mkiv/lpdf-ano.lua
index 01f015b72..49bf973c9 100644
--- a/tex/context/base/mkiv/lpdf-ano.lua
+++ b/tex/context/base/mkiv/lpdf-ano.lua
@@ -18,6 +18,7 @@ local rep, format, find = string.rep, string.format, string.find
local min = math.min
local lpegmatch = lpeg.match
local formatters = string.formatters
+local sortedkeys = table.sortedkeys
local backends, lpdf = backends, lpdf
@@ -48,10 +49,6 @@ local nodeinjections = backends.pdf.nodeinjections
local codeinjections = backends.pdf.codeinjections
local registrations = backends.pdf.registrations
-local getpos = codeinjections.getpos
-local gethpos = codeinjections.gethpos
-local getvpos = codeinjections.getvpos
-
local javascriptcode = interactions.javascripts.code
local references = structures.references
@@ -68,12 +65,15 @@ local executers = references.executers
local nodepool = nodes.pool
------ pdfannotation_node = nodepool.pdfannotation
------ pdfdestination_node = nodepool.pdfdestination
local new_latelua = nodepool.latelua
local texgetcount = tex.getcount
+local jobpositions = job.positions
+local getpos = jobpositions.getpos
+local gethpos = jobpositions.gethpos
+local getvpos = jobpositions.getvpos
+
local pdfdictionary = lpdf.dictionary
local pdfarray = lpdf.array
local pdfreference = lpdf.reference
@@ -106,6 +106,32 @@ local pdf_fit = pdfconstant("Fit")
local pdf_named = pdfconstant("Named")
local autoprefix = "#"
+local usedautoprefixes = { }
+
+local function registerautoprefix(name)
+ local internal = autoprefix .. name
+ if usedautoprefixes[internal] == nil then
+ usedautoprefixes[internal] = false
+ end
+ return internal
+end
+
+local function useautoprefix(name)
+ local internal = autoprefix .. name
+ usedautoprefixes[internal] = true
+ return internal
+end
+
+local function checkautoprefixes(destinations)
+ for k, v in next, usedautoprefixes do
+ if not v then
+ if trace_destinations then
+ report_destinations("flushing unused autoprefix %a",k)
+ end
+ destinations[k] = nil
+ end
+ end
+end
-- Bah, I hate this kind of features .. anyway, as we have delayed resolving we
-- only support a document-wide setup and it has to be set before the first one
@@ -113,9 +139,9 @@ local autoprefix = "#"
-- thin without dashing lines. This is as far as I'm prepared to go. This way
-- it can also be used as a debug feature.
-local pdf_border_style = pdfarray { 0, 0, 0 } -- radius radius linewidth
-local pdf_border_color = nil
-local set_border = false
+local pdf_border_style = pdfarray { 0, 0, 0 } -- radius radius linewidth
+local pdf_border_color = nil
+local set_border = false
local function pdfborder()
set_border = true
@@ -131,7 +157,9 @@ directives.register("references.border",function(v)
local c = m and m[v]
local v = c and attributes.colors.value(c)
if v then
- local r, g, b = v[3], v[4], v[5]
+ local r = v[3]
+ local g = v[4]
+ local b = v[5]
-- if r == g and g == b then
-- pdf_border_color = pdfarray { r } -- reduced, not not ... bugged viewers
-- else
@@ -192,12 +220,16 @@ local defaultdestination = pdfarray { 0, pdf_fit }
-- fit is default (see lpdf-nod)
-local destinations = { } -- to be used soon
+local destinations = { }
+local reported = setmetatableindex("table")
local function pdfregisterdestination(name,reference)
local d = destinations[name]
if d then
- report_destinations("ignoring duplicate destination %a with reference %a",name,reference)
+ if not reported[name][reference] then
+ report_destinations("ignoring duplicate destination %a with reference %a",name,reference)
+ reported[name][reference] = true
+ end
else
destinations[name] = reference
end
@@ -222,7 +254,11 @@ end)
local function pdfnametree(destinations)
local slices = { }
- local sorted = table.sortedkeys(destinations)
+ checkautoprefixes(destinations)
+ if not next(destinations) then
+ return
+ end
+ local sorted = sortedkeys(destinations)
local size = #sorted
if size <= 1.5*maxslice then
@@ -232,11 +268,12 @@ local function pdfnametree(destinations)
for i=1,size,maxslice do
local amount = min(i+maxslice-1,size)
local names = pdfarray { }
+ local n = 0
for j=i,amount do
local destination = sorted[j]
local pagenumber = destinations[destination]
- names[#names+1] = tostring(destination) -- tostring is a safeguard
- names[#names+1] = pdfreference(pagenumber)
+ n = n + 1 ; names[n] = tostring(destination) -- tostring is a safeguard
+ n = n + 1 ; names[n] = pdfreference(pagenumber)
end
local first = sorted[i]
local last = sorted[amount]
@@ -254,18 +291,23 @@ local function pdfnametree(destinations)
}
end
local function collectkids(slices,first,last)
- local k = pdfarray()
- local d = pdfdictionary {
- Kids = k,
- Limits = pdfarray {
- slices[first].limits[1],
- slices[last ].limits[2],
- },
- }
- for i=first,last do
- k[#k+1] = slices[i].reference
+ local f = slices[first]
+ local l = slices[last]
+ if f and l then
+ local k = pdfarray()
+ local n = 0
+ local d = pdfdictionary {
+ Kids = k,
+ Limits = pdfarray {
+ f.limits[1],
+ l.limits[2],
+ },
+ }
+ for i=first,last do
+ n = n + 1 ; k[n] = slices[i].reference
+ end
+ return d
end
- return d
end
if #slices == 1 then
return slices[1].reference
@@ -276,14 +318,24 @@ local function pdfnametree(destinations)
local size = #slices
for i=1,size,maxslice do
local kids = collectkids(slices,i,min(i+maxslice-1,size))
- temp[#temp+1] = {
- reference = pdfreference(pdfflushobject(kids)),
- limits = kids.Limits,
- }
+ if kids then
+ temp[#temp+1] = {
+ reference = pdfreference(pdfflushobject(kids)),
+ limits = kids.Limits,
+ }
+ else
+ -- error
+ end
end
slices = temp
else
- return pdfreference(pdfflushobject(collectkids(slices,1,#slices)))
+ local kids = collectkids(slices,1,#slices)
+ if kids then
+ return pdfreference(pdfflushobject(kids))
+ else
+ -- error
+ return
+ end
end
end
end
@@ -292,8 +344,9 @@ end
local function pdfdestinationspecification()
if next(destinations) then -- safeguard
local r = pdfnametree(destinations)
- -- pdfaddtocatalog("Dests",r)
- pdfaddtonames("Dests",r)
+ if r then
+ pdfaddtonames("Dests",r)
+ end
if not log_destinations then
destinations = nil
end
@@ -309,14 +362,25 @@ lpdf.registerdocumentfinalizer(pdfdestinationspecification,"collect destinations
local destinations = { }
-local f_xyz = formatters["<< /D [ %i 0 R /XYZ %0.3F %0.3F null ] >>"]
+local f_xyz = formatters["<< /D [ %i 0 R /XYZ %.6F %.6F null ] >>"]
local f_fit = formatters["<< /D [ %i 0 R /Fit ] >>"]
local f_fitb = formatters["<< /D [ %i 0 R /FitB ] >>"]
-local f_fith = formatters["<< /D [ %i 0 R /FitH %0.3F ] >>"]
-local f_fitv = formatters["<< /D [ %i 0 R /FitV %0.3F ] >>"]
-local f_fitbh = formatters["<< /D [ %i 0 R /FitBH %0.3F ] >>"]
-local f_fitbv = formatters["<< /D [ %i 0 R /FitBV %0.3F ] >>"]
-local f_fitr = formatters["<< /D [ %i 0 R /FitR %0.3F %0.3F %0.3F %0.3F ] >>"]
+local f_fith = formatters["<< /D [ %i 0 R /FitH %.6F ] >>"]
+local f_fitv = formatters["<< /D [ %i 0 R /FitV %.6F ] >>"]
+local f_fitbh = formatters["<< /D [ %i 0 R /FitBH %.6F ] >>"]
+local f_fitbv = formatters["<< /D [ %i 0 R /FitBV %.6F ] >>"]
+local f_fitr = formatters["<< /D [ %i 0 R /FitR %.6F %.6F %.6F %.6F ] >>"]
+
+directives.register("pdf.stripzeros",function()
+ f_xyz = formatters["<< /D [ %i 0 R /XYZ %.6N %.6N null ] >>"]
+ f_fit = formatters["<< /D [ %i 0 R /Fit ] >>"]
+ f_fitb = formatters["<< /D [ %i 0 R /FitB ] >>"]
+ f_fith = formatters["<< /D [ %i 0 R /FitH %.6N ] >>"]
+ f_fitv = formatters["<< /D [ %i 0 R /FitV %.6N ] >>"]
+ f_fitbh = formatters["<< /D [ %i 0 R /FitBH %.6N ] >>"]
+ f_fitbv = formatters["<< /D [ %i 0 R /FitBV %.6N ] >>"]
+ f_fitr = formatters["<< /D [ %i 0 R /FitR %.6N %.6N %.6N %.6N ] >>"]
+end)
local v_standard = variables.standard
local v_frame = variables.frame
@@ -404,13 +468,15 @@ local pagedestinations = setmetatableindex(function(t,k) -- not the same as the
return v
end)
-local function flushdestination(width,height,depth,names,view)
- local r = pdfpagereference(texgetcount("realpageno"))
+local function flushdestination(specification)
+ local names = specification.names
+ local view = specification.view
+ local r = pdfpagereference(texgetcount("realpageno"))
if (references.innermethod ~= v_name) and (view == defaultview or not view or view == "") then
r = pagedestinations[r]
else
local action = view and destinationactions[view] or defaultaction
- r = pdfdelayedobject(action(r,width,height,depth,offset))
+ r = pdfdelayedobject(action(r,specification.width,specification.height,specification.depth,offset))
end
for n=1,#names do
local name = names[n]
@@ -459,7 +525,7 @@ function nodeinjections.destination(width,height,depth,names,view)
elseif type(name) == "number" then
local used = usedinternals[name]
usedviews[name] = view
- names[n] = autoprefix .. name
+ names[n] = registerautoprefix(name)
doview = true
else
usedviews[name] = view
@@ -479,10 +545,9 @@ function nodeinjections.destination(width,height,depth,names,view)
local used = usedinternals[name]
if used and used ~= defaultview then
usedviews[name] = view
- names[n] = autoprefix .. name
+ names[n] = registerautoprefix(name)
doview = true
else
- -- names[n] = autoprefix .. name
names[n] = false
end
end
@@ -493,7 +558,14 @@ function nodeinjections.destination(width,height,depth,names,view)
end
end
if doview then
- return new_latelua(function() flushdestination(width,height,depth,names,view) end)
+ return new_latelua {
+ action = flushdestination,
+ width = width,
+ height = height,
+ depth = depth,
+ names = names,
+ view = view,
+ }
end
end
@@ -504,7 +576,7 @@ local function pdflinkpage(page)
end
local function pdflinkinternal(internal,page)
- local method = references.innermethod
+ -- local method = references.innermethod
if internal then
flaginternals[internal] = true -- for bookmarks and so
local used = usedinternals[internal]
@@ -512,7 +584,7 @@ local function pdflinkinternal(internal,page)
return pagereferences[page]
else
if type(internal) ~= "string" then
- internal = autoprefix .. internal
+ internal = useautoprefix(internal)
end
return pdfdictionary {
S = pdf_goto,
@@ -559,7 +631,7 @@ local function pdffilelink(filename,destination,page,actions)
end
filename = file.addsuffix(filename,"pdf")
if (not destination or destination == "") or (references.outermethod == v_page) then
- destination = pdfarray { (page or 0) - 1, pdf_fit }
+ destination = pdfarray { (page or 1) - 1, pdf_fit }
end
return pdfdictionary {
S = pdf_gotor, -- can also be pdf_launch
@@ -635,7 +707,7 @@ local function pdfaction(actions)
return nil
end
end
- return first, actions.n
+ return first, actions.n or #actions
end
end
end
@@ -686,9 +758,15 @@ local nofused = 0
local nofspecial = 0
local share = true
-local f_annot = formatters["<< /Type /Annot %s /Rect [ %0.3F %0.3F %0.3F %0.3F ] >>"]
+local f_annot = formatters["<< /Type /Annot %s /Rect [ %0.6F %0.6F %0.6F %0.6F ] >>"]
-directives.register("references.sharelinks", function(v) share = v end)
+directives.register("pdf.stripzeros",function()
+ f_annot = formatters["<< /Type /Annot %s /Rect [ %0.6N %0.6N %0.6N %0.6N ] >>"]
+end)
+
+directives.register("references.sharelinks", function(v)
+ share = v
+end)
setmetatableindex(hashed,function(t,k)
local v = pdfdelayedobject(k)
@@ -699,24 +777,26 @@ setmetatableindex(hashed,function(t,k)
return v
end)
-local function finishreference(width,height,depth,prerolled) -- %0.2f looks okay enough (no scaling anyway)
- local annot = hashed[f_annot(prerolled,pdfrectangle(width,height,depth))]
+local function finishreference(specification) -- %0.2f looks okay enough (no scaling anyway)
+ local annot = hashed[f_annot(specification.prerolled,pdfrectangle(specification.width,specification.height,specification.depth))]
nofused = nofused + 1
return pdfregisterannotation(annot)
end
-local function finishannotation(width,height,depth,prerolled,r)
+local function finishannotation(specification)
+ local prerolled = specification.prerolled
+ local objref = specification.objref
if type(prerolled) == "function" then
prerolled = prerolled()
end
- local annot = f_annot(prerolled,pdfrectangle(width,height,depth))
- if r then
- pdfdelayedobject(annot,r)
+ local annot = f_annot(prerolled,pdfrectangle(specification.width,specification.height,specification.depth))
+ if objref then
+ pdfdelayedobject(annot,objref)
else
- r = pdfdelayedobject(annot)
+ objref = pdfdelayedobject(annot)
end
nofspecial = nofspecial + 1
- return pdfregisterannotation(r)
+ return pdfregisterannotation(objref)
end
function nodeinjections.reference(width,height,depth,prerolled)
@@ -724,17 +804,30 @@ function nodeinjections.reference(width,height,depth,prerolled)
if trace_references then
report_references("link: width %p, height %p, depth %p, prerolled %a",width,height,depth,prerolled)
end
- return new_latelua(function() finishreference(width,height,depth,prerolled) end)
+ return new_latelua {
+ action = finishreference,
+ width = width,
+ height = height,
+ depth = depth,
+ prerolled = prerolled,
+ }
end
end
-function nodeinjections.annotation(width,height,depth,prerolled,r)
+function nodeinjections.annotation(width,height,depth,prerolled,objref)
if prerolled then
if trace_references then
report_references("special: width %p, height %p, depth %p, prerolled %a",width,height,depth,
type(prerolled) == "string" and prerolled or "-")
end
- return new_latelua(function() finishannotation(width,height,depth,prerolled,r or false) end)
+ return new_latelua {
+ action = finishannotation,
+ width = width,
+ height = height,
+ depth = depth,
+ prerolled = prerolled,
+ objref = objref or false,
+ }
end
end
@@ -757,7 +850,9 @@ pdfregisterannotation = lpdf.registerannotation
function lpdf.annotationspecification()
if annotations then
local r = pdfdelayedobject(tostring(annotations)) -- delayed so okay in latelua
- pdfaddtopageattributes("Annots",pdfreference(r))
+ if r then
+ pdfaddtopageattributes("Annots",pdfreference(r))
+ end
annotations = nil
end
end
@@ -872,16 +967,21 @@ end
runners["special operation"] = runners["special"]
runners["special operation with arguments"] = runners["special"]
+local reported = { }
+
function specials.internal(var,actions) -- better resolve in strc-ref
- local i = tonumber(var.operation)
+ local o = var.operation
+ local i = o and tonumber(o)
local v = i and references.internals[i]
- if not v then
- -- error
- report_references("no internal reference %a",i or "<unset>")
- else
- flaginternals[i] = true
+ if v then
+ flaginternals[i] = true -- also done in pdflinkinternal
return pdflinkinternal(i,v.references.realpage)
end
+ local v = i or o or "<unset>"
+ if not reported[v] then
+ report_references("no internal reference %a",v)
+ reported[v] = true
+ end
end
-- realpage already resolved
@@ -946,19 +1046,18 @@ end
-- sections
--- function specials.section(var,actions)
--- local sectionname = var.operation
--- local destination = var.arguments
--- local internal = structures.sections.internalreference(sectionname,destination)
--- if internal then
--- var.special = "internal"
--- var.operation = internal
--- var.arguments = nil
--- specials.internal(var,actions)
--- end
--- end
-
-specials.section = specials.internal -- specials.section just need to have a value as it's checked
+function specials.section(var,actions)
+ -- a bit duplicate
+ local sectionname = var.arguments
+ local destination = var.operation
+ local internal = structures.sections.internalreference(sectionname,destination)
+ if internal then
+ var.special = "internal"
+ var.operation = internal
+ var.arguments = nil
+ return specials.internal(var,actions)
+ end
+end
-- todo, do this in references namespace ordered instead (this is an experiment)
@@ -1129,7 +1228,8 @@ end
local function build(levels,start,parent,method,nested)
local startlevel = levels[start].level
local noflevels = #levels
- local i, n = start, 0
+ local i = start
+ local n = 0
local child, entry, m, prev, first, last, f, l
while i and i <= noflevels do
local current = levels[i]
@@ -1146,11 +1246,12 @@ local function build(levels,start,parent,method,nested)
local variant = "unknown"
if reftype == "table" then
-- we're okay
- variant = "list"
- block = reference.block
+ variant = "list"
+ block = reference.block
+ realpage = reference.realpage
elseif reftype == "string" then
local resolved = references.identify("",reference)
- local realpage = resolved and structures.references.setreferencerealpage(resolved) or 0
+ realpage = resolved and structures.references.setreferencerealpage(resolved) or 0
if realpage > 0 then
variant = "realpage"
realpage = realpage
@@ -1251,7 +1352,6 @@ end
function codeinjections.addbookmarks(levels,method)
if levels and #levels > 0 then
--- inspect(levels)
local parent = pdfreserveobject()
local _, m, first, last = build(levels,1,pdfreference(parent),method or "internal",false)
local dict = pdfdictionary {
diff --git a/tex/context/base/mkiv/lpdf-aux.lua b/tex/context/base/mkiv/lpdf-aux.lua
new file mode 100644
index 000000000..0d7cecbb8
--- /dev/null
+++ b/tex/context/base/mkiv/lpdf-aux.lua
@@ -0,0 +1,152 @@
+if not modules then modules = { } end modules ['lpdf-aux'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local tonumber = tonumber
+local format, concat = string.format, table.concat
+local utfchar, utfbyte, char = utf.char, utf.byte, string.char
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local P, C, R, S, Cc, Cs, V = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs, lpeg.V
+local rshift = bit32.rshift
+
+lpdf = lpdf or { }
+
+-- tosixteen --
+
+local cache = table.setmetatableindex(function(t,k) -- can be made weak
+ local v = utfbyte(k)
+ if v < 0x10000 then
+ v = format("%04x",v)
+ else
+ v = format("%04x%04x",rshift(v,10),v%1024+0xDC00)
+ end
+ t[k] = v
+ return v
+end)
+
+local unified = Cs(Cc("<feff") * (lpegpatterns.utf8character/cache)^1 * Cc(">"))
+
+function lpdf.tosixteen(str) -- an lpeg might be faster (no table)
+ if not str or str == "" then
+ return "<feff>" -- not () as we want an indication that it's unicode
+ else
+ return lpegmatch(unified,str)
+ end
+end
+
+-- fromsixteen --
+
+-- local zero = S(" \n\r\t") + P("\\ ")
+-- local one = C(4)
+-- local two = P("d") * R("89","af") * C(2) * C(4)
+--
+-- local pattern = P { "start",
+-- start = V("wrapped") + V("unwrapped") + V("original"),
+-- original = Cs(P(1)^0),
+-- wrapped = P("<") * V("unwrapped") * P(">") * P(-1),
+-- unwrapped = P("feff")
+-- * Cs( (
+-- zero / ""
+-- + two / function(a,b)
+-- a = (tonumber(a,16) - 0xD800) * 1024
+-- b = (tonumber(b,16) - 0xDC00)
+-- return utfchar(a+b)
+-- end
+-- + one / function(a)
+-- return utfchar(tonumber(a,16))
+-- end
+-- )^1 ) * P(-1)
+-- }
+--
+-- function lpdf.fromsixteen(s)
+-- return lpegmatch(pattern,s) or s
+-- end
+
+local more = 0
+
+local pattern = C(4) / function(s) -- needs checking !
+ local now = tonumber(s,16)
+ if more > 0 then
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
+ more = 0
+ return utfchar(now)
+ elseif now >= 0xD800 and now <= 0xDBFF then
+ more = now
+ return "" -- else the c's end up in the stream
+ else
+ return utfchar(now)
+ end
+end
+
+local pattern = P(true) / function() more = 0 end * Cs(pattern^0)
+
+function lpdf.fromsixteen(str)
+ if not str or str == "" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+end
+
+-- frombytes --
+
+local b_pattern = Cs((P("\\")/"" * (
+ S("()")
+ + S("nrtbf")/ { n = "\n", r = "\r", t = "\t", b = "\b", f = "\f" }
+ + lpegpatterns.octdigit^-3 / function(s) return char(tonumber(s,8)) end)
++ P(1))^0)
+
+local u_pattern = lpegpatterns.utfbom_16_be * lpegpatterns.utf16_to_utf8_be -- official
+ + lpegpatterns.utfbom_16_le * lpegpatterns.utf16_to_utf8_le -- we've seen these
+
+local h_pattern = lpegpatterns.hextobytes
+
+local zero = S(" \n\r\t") + P("\\ ")
+local one = C(4)
+local two = P("d") * R("89","af") * C(2) * C(4)
+
+local x_pattern = P { "start",
+ start = V("wrapped") + V("unwrapped") + V("original"),
+ original = Cs(P(1)^0),
+ wrapped = P("<") * V("unwrapped") * P(">") * P(-1),
+ unwrapped = P("feff")
+ * Cs( (
+ zero / ""
+ + two / function(a,b)
+ a = (tonumber(a,16) - 0xD800) * 1024
+ b = (tonumber(b,16) - 0xDC00)
+ return utfchar(a+b)
+ end
+ + one / function(a)
+ return utfchar(tonumber(a,16))
+ end
+ )^1 ) * P(-1)
+}
+
+function lpdf.frombytes(s,hex)
+ if not s or s == "" then
+ return ""
+ end
+ if hex then
+ local x = lpegmatch(x_pattern,s)
+ if x then
+ return x
+ end
+ local h = lpegmatch(h_pattern,s)
+ if h then
+ return h
+ end
+ else
+ local u = lpegmatch(u_pattern,s)
+ if u then
+ return u
+ end
+ end
+ return lpegmatch(b_pattern,s)
+end
+
+-- done --
diff --git a/tex/context/base/mkiv/lpdf-col.lua b/tex/context/base/mkiv/lpdf-col.lua
index d1a1af97d..b697dc481 100644
--- a/tex/context/base/mkiv/lpdf-col.lua
+++ b/tex/context/base/mkiv/lpdf-col.lua
@@ -23,7 +23,7 @@ local registrations = backends.pdf.registrations
local nodepool = nodes.nuts.pool
local register = nodepool.register
-local pdfpageliteral = nodepool.pdfpageliteral
+local pageliteral = nodepool.pageliteral
local pdfconstant = lpdf.constant
local pdfdictionary = lpdf.dictionary
@@ -64,13 +64,20 @@ local f_cmyk = formatters["%.3F %.3F %.3F %.3F k %.3F %.3F %.3F %.3F K"]
local f_spot = formatters["/%s cs /%s CS %s SCN %s scn"]
local f_tr = formatters["Tr%s"]
local f_cm = formatters["q %.6F %.6F %.6F %.6F %.6F %.6F cm"]
-local f_effect = formatters["%s Tc %s w %s Tr"]
+local f_effect = formatters["%s Tc %s w %s Tr"] -- %.3F ?
local f_tr_gs = formatters["/Tr%s gs"]
local f_num_1 = tostring
local f_num_2 = formatters["%s %s"]
local f_num_3 = formatters["%s %s %s"]
local f_num_4 = formatters["%s %s %s %s"]
+directives.register("pdf.stripzeros",function()
+ f_gray = formatters["%.3N g %.3N G"]
+ f_rgb = formatters["%.3N %.3N %.3N rg %.3N %.3N %.3N RG"]
+ f_cmyk = formatters["%.3N %.3N %.3N %.3N k %.3N %.3N %.3N %.3N K"]
+ f_cm = formatters["q %.6N %.6N %.6N %.6N %.6N %.6N cm"]
+end)
+
local report_color = logs.reporter("colors","backend")
-- page groups (might move to lpdf-ini.lua)
@@ -122,26 +129,26 @@ lpdf.registerpagefinalizer(addpagegroup,3,"pagegroup")
-- color injection
function nodeinjections.rgbcolor(r,g,b)
- return register(pdfpageliteral(f_rgb(r,g,b,r,g,b)))
+ return register(pageliteral(f_rgb(r,g,b,r,g,b)))
end
function nodeinjections.cmykcolor(c,m,y,k)
- return register(pdfpageliteral(f_cmyk(c,m,y,k,c,m,y,k)))
+ return register(pageliteral(f_cmyk(c,m,y,k,c,m,y,k)))
end
function nodeinjections.graycolor(s) -- caching 0/1 does not pay off
- return register(pdfpageliteral(f_gray(s,s)))
+ return register(pageliteral(f_gray(s,s)))
end
function nodeinjections.spotcolor(n,f,d,p)
if type(p) == "string" then
p = gsub(p,","," ") -- brr misuse of spot
end
- return register(pdfpageliteral(f_spot(n,n,p,p)))
+ return register(pageliteral(f_spot(n,n,p,p)))
end
function nodeinjections.transparency(n)
- return register(pdfpageliteral(f_tr_gs(n)))
+ return register(pageliteral(f_tr_gs(n)))
end
-- a bit weird but let's keep it here for a while
@@ -160,7 +167,7 @@ function nodeinjections.effect(effect,stretch,rulethickness)
-- always, no zero test (removed)
rulethickness = bp * rulethickness
effect = effects[effect] or effects['normal']
- return register(pdfpageliteral(f_effect(stretch,rulethickness,effect))) -- watch order
+ return register(pageliteral(f_effect(stretch,rulethickness,effect))) -- watch order
end
-- spot- and indexcolors
@@ -335,7 +342,9 @@ local function registersomeindexcolor(name,noffractions,names,p,colorspace,range
colorspace,
pdfreference(n),
}
- local vector, set, n = { }, { }, #values
+ local vector = { }
+ local set = { }
+ local n = #values
for i=255,0,-1 do
for j=1,n do
set[j] = format("%02X",round(values[j]*i))
@@ -512,13 +521,21 @@ local function lpdfcolor(model,ca,default) -- todo: use gray when no color
local s = cv[2]
return f_gray(s,s)
elseif model == 3 then
- local r, g, b = cv[3], cv[4], cv[5]
+ local r = cv[3]
+ local g = cv[4]
+ local b = cv[5]
return f_rgb(r,g,b,r,g,b)
elseif model == 4 then
- local c, m, y, k = cv[6],cv[7],cv[8],cv[9]
+ local c = cv[6]
+ local m = cv[7]
+ local y = cv[8]
+ local k = cv[9]
return f_cmyk(c,m,y,k,c,m,y,k)
else
- local n,f,d,p = cv[10],cv[11],cv[12],cv[13]
+ local n = cv[10]
+ local f = cv[11]
+ local d = cv[12]
+ local p = cv[13]
if type(p) == "string" then
p = gsub(p,","," ") -- brr misuse of spot
end
@@ -617,7 +634,7 @@ function lpdf.colorvalues(model,ca,default)
return cv[3], cv[4], cv[5]
elseif model == 4 then
return cv[6], cv[7], cv[8], cv[9]
- elseif model == 4 then
+ elseif model == 5 then
return cv[13]
end
else
@@ -717,6 +734,10 @@ do
local f_slant = formatters["q 1 0 %.6F 1 0 0 cm"]
+ directives.register("pdf.stripzeros",function()
+ f_slant = formatters["q 1 0 %.6N 1 0 0 cm"]
+ end)
+
-- local fillcolors = {
-- red = { "pdf", "origin", "1 0 0 rg" },
-- green = { "pdf", "origin", "0 1 0 rg" },
diff --git a/tex/context/base/mkiv/lpdf-epa.lua b/tex/context/base/mkiv/lpdf-epa.lua
index 89b2c6e0e..570d73881 100644
--- a/tex/context/base/mkiv/lpdf-epa.lua
+++ b/tex/context/base/mkiv/lpdf-epa.lua
@@ -6,49 +6,79 @@ if not modules then modules = { } end modules ['lpdf-epa'] = {
license = "see context related readme files"
}
--- This is a rather experimental feature and the code will probably change.
+-- Links can also have quadpoint
-local type, tonumber = type, tonumber
-local format, gsub, lower = string.format, string.gsub, string.lower
+-- embedded files ... not bound to a page
+
+local type, tonumber, next = type, tonumber, next
+local format, gsub, lower, find = string.format, string.gsub, string.lower, string.find
local formatters = string.formatters
+local concat, merged = table.concat, table.merged
local abs = math.abs
local expandname = file.expandname
local allocate = utilities.storage.allocate
+local bor, band = bit32.bor, bit32.band
local isfile = lfs.isfile
------ lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local trace_links = false trackers.register("figures.links", function(v) trace_links = v end)
+local trace_comments = false trackers.register("figures.comments", function(v) trace_comments = v end)
+local trace_fields = false trackers.register("figures.fields", function(v) trace_fields = v end)
+local trace_outlines = false trackers.register("figures.outlines", function(v) trace_outlines = v end)
+
+local report_link = logs.reporter("backend","link")
+local report_comment = logs.reporter("backend","comment")
+local report_field = logs.reporter("backend","field")
+local report_outline = logs.reporter("backend","outline")
+
+local lpdf = lpdf
+local epdf = epdf
+local backends = backends
+local context = context
+
+local nodeinjections = backends.pdf.nodeinjections
+
+local pdfarray = lpdf.array
+local pdfdictionary = lpdf.dictionary
+local pdfconstant = lpdf.constant
+local pdfreserveobject = lpdf.reserveobject
+local pdfreference = lpdf.reference
-local trace_links = false trackers.register("figures.links", function(v) trace_links = v end)
-local trace_outlines = false trackers.register("figures.outliness", function(v) trace_outlines = v end)
+local pdfcopyboolean = lpdf.copyboolean
+local pdfcopyunicode = lpdf.copyunicode
+local pdfcopyarray = lpdf.copyarray
+local pdfcopydictionary = lpdf.copydictionary
+local pdfcopynumber = lpdf.copynumber
+local pdfcopyinteger = lpdf.copyinteger
+local pdfcopystring = lpdf.copystring
+local pdfcopyconstant = lpdf.copyconstant
-local report_link = logs.reporter("backend","link")
-local report_comment = logs.reporter("backend","comment")
-local report_field = logs.reporter("backend","field")
-local report_outline = logs.reporter("backend","outline")
+local createimage = images.create
+local embedimage = images.embed
-local epdf = epdf
-local backends = backends
-local lpdf = lpdf
-local context = context
+local hpack_node = nodes.hpack
-local loadpdffile = lpdf.epdf.load
+local loadpdffile = lpdf.epdf.load
-local nameonly = file.nameonly
+local nameonly = file.nameonly
-local variables = interfaces.variables
-local codeinjections = backends.pdf.codeinjections
------ urlescaper = lpegpatterns.urlescaper
------ utftohigh = lpegpatterns.utftohigh
-local escapetex = characters.filters.utf.private.escape
+local variables = interfaces.variables
+local codeinjections = backends.pdf.codeinjections
+----- urlescaper = lpegpatterns.urlescaper
+----- utftohigh = lpegpatterns.utftohigh
+local escapetex = characters.filters.utf.private.escape
-local bookmarks = structures.bookmarks
+local bookmarks = structures.bookmarks
-local maxdimen = 0x3FFFFFFF -- 2^30-1
+local maxdimen = 0x3FFFFFFF -- 2^30-1
+
+local bpfactor = number.dimenfactors.bp
local layerspec = { -- predefining saves time
- "epdflinks"
+ "epdfcontent"
}
+local getpos = function() getpos = backends.codeinjections.getpos return getpos () end
+
local collected = allocate()
local tobesaved = allocate()
@@ -66,6 +96,68 @@ end
job.register('job.embedded.collected',tobesaved,initializer)
+local function validdocument(specification)
+ if figures and not specification then
+ specification = figures and figures.current()
+ specification = specification and specification.status
+ end
+ if specification then
+ local fullname = specification.fullname
+ local expanded = lower(expandname(fullname))
+ -- we could add a check for duplicate page insertion
+ tobesaved[expanded] = true
+ --- but that is messy anyway so we forget about it
+ return specification, fullname, loadpdffile(fullname) -- costs time
+ end
+end
+
+local function getmediasize(specification,pagedata)
+ local xscale = specification.xscale or 1
+ local yscale = specification.yscale or 1
+ ----- size = specification.size or "crop" -- todo
+ local mediabox = pagedata.MediaBox
+ local llx = mediabox[1]
+ local lly = mediabox[2]
+ local urx = mediabox[3]
+ local ury = mediabox[4]
+ local width = xscale * (urx - llx) -- \\overlaywidth, \\overlayheight
+ local height = yscale * (ury - lly) -- \\overlaywidth, \\overlayheight
+ return llx, lly, urx, ury, width, height, xscale, yscale
+end
+
+local function getdimensions(annotation,llx,lly,xscale,yscale,width,height,report)
+ local rectangle = annotation.Rect
+ local a_llx = rectangle[1]
+ local a_lly = rectangle[2]
+ local a_urx = rectangle[3]
+ local a_ury = rectangle[4]
+ local x = xscale * (a_llx - llx)
+ local y = yscale * (a_lly - lly)
+ local w = xscale * (a_urx - a_llx)
+ local h = yscale * (a_ury - a_lly)
+ if w > width or h > height or w < 0 or h < 0 or abs(x) > (maxdimen/2) or abs(y) > (maxdimen/2) then
+ report("broken rectangle [%.6F %.6F %.6F %.6F] (max: %.6F)",a_llx,a_lly,a_urx,a_ury,maxdimen/2)
+ return
+ end
+ return x, y, w, h, a_llx, a_lly, a_urx, a_ury
+end
+
+local layerused = false
+
+local function initializelayer(height,width)
+ if not layerused then
+ context.definelayer(layerspec, { height = height .. "bp", width = width .. "bp" })
+ layerused = true
+ end
+end
+
+function codeinjections.flushmergelayer()
+ if layerused then
+ context.flushlayer(layerspec)
+ layerused = false
+ end
+end
+
local f_namespace = formatters["lpdf-epa-%s-"]
local function makenamespace(filename)
@@ -182,82 +274,51 @@ local function link_file(x,y,w,h,document,annotation)
end
end
+-- maybe handler per subtype and then one loop but then what about order ...
+
function codeinjections.mergereferences(specification)
- if figures and not specification then
- specification = figures and figures.current()
- specification = specification and specification.status
- end
- if not specification then
- return ""
- end
- local fullname = specification.fullname
- local expanded = lower(expandname(fullname))
- -- we could add a check for duplicate page insertion
- tobesaved[expanded] = true
- --- but that is messy anyway so we forget about it
- local document = loadpdffile(fullname) -- costs time
+ local specification, fullname, document = validdocument(specification)
if not document then
return ""
end
- local pagenumber = specification.page or 1
- local xscale = specification.yscale or 1
- local yscale = specification.yscale or 1
- local size = specification.size or "crop" -- todo
+ local pagenumber = specification.page or 1
local pagedata = document.pages[pagenumber]
local annotations = pagedata and pagedata.Annots
local namespace = makenamespace(fullname)
local reference = namespace .. pagenumber
- if annotations and annotations.n > 0 then
- local mediabox = pagedata.MediaBox
- local llx = mediabox[1]
- local lly = mediabox[2]
- local urx = mediabox[3]
- local ury = mediabox[4]
- local width = xscale * (urx - llx) -- \\overlaywidth, \\overlayheight
- local height = yscale * (ury - lly) -- \\overlaywidth, \\overlayheight
- context.definelayer( { "epdflinks" }, { height = height.."bp" , width = width.."bp" })
- for i=1,annotations.n do
+ if annotations and #annotations > 0 then
+ local llx, lly, urx, ury, width, height, xscale, yscale = getmediasize(specification,pagedata,xscale,yscale)
+ initializelayer(height,width)
+ for i=1,#annotations do
local annotation = annotations[i]
if annotation then
- local subtype = annotation.Subtype
- local rectangle = annotation.Rect
- local a_llx = rectangle[1]
- local a_lly = rectangle[2]
- local a_urx = rectangle[3]
- local a_ury = rectangle[4]
- local x = xscale * (a_llx - llx)
- local y = yscale * (a_lly - lly)
- local w = xscale * (a_urx - a_llx)
- local h = yscale * (a_ury - a_lly)
- if subtype == "Link" then
+ if annotation.Subtype == "Link" then
local a = annotation.A
if not a then
report_link("missing link annotation")
- elseif w > width or h > height or w < 0 or h < 0 or abs(x) > (maxdimen/2) or abs(y) > (maxdimen/2) then
- report_link("broken link rectangle [%.6F %.6F %.6F %.6F] (max: %.6F)",a_llx,a_lly,a_urx,a_ury,maxdimen/2)
else
- local linktype = a.S
- if linktype == "GoTo" then
- link_goto(x,y,w,h,document,annotation,pagedata,namespace)
- elseif linktype == "GoToR" then
- link_file(x,y,w,h,document,annotation)
- elseif linktype == "URI" then
- link_uri(x,y,w,h,document,annotation)
- elseif trace_links then
- report_link("unsupported link annotation %a",linktype)
+ local x, y, w, h = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_link)
+ if x then
+ local linktype = a.S
+ if linktype == "GoTo" then
+ link_goto(x,y,w,h,document,annotation,pagedata,namespace)
+ elseif linktype == "GoToR" then
+ link_file(x,y,w,h,document,annotation)
+ elseif linktype == "URI" then
+ link_uri(x,y,w,h,document,annotation)
+ elseif trace_links then
+ report_link("unsupported link annotation %a",linktype)
+ end
end
end
- elseif trace_links then
- report_link("unsupported annotation %a",subtype)
end
elseif trace_links then
report_link("broken annotation, index %a",i)
end
end
- context.flushlayer { "epdflinks" }
end
-- moved outside previous test
- context.setgvalue("figurereference",reference) -- global
+ context.setgvalue("figurereference",reference) -- global, todo: setmacro
if trace_links then
report_link("setting figure reference to %a",reference)
end
@@ -270,43 +331,527 @@ function codeinjections.mergeviewerlayers(specification)
if true then
return
end
- if not specification then
- specification = figures and figures.current()
- specification = specification and specification.status
+ local specification, fullname, document = validdocument(specification)
+ if not document then
+ return ""
end
- if specification then
- local fullname = specification.fullname
- local document = loadpdffile(fullname)
- if document then
- local namespace = makenamespace(fullname)
- local layers = document.layers
- if layers then
- for i=1,layers.n do
- local layer = layers[i]
- if layer then
- local tag = namespace .. gsub(layer," ",":")
- local title = tag
- if trace_links then
- report_link("using layer %a",tag)
+ local namespace = makenamespace(fullname)
+ local layers = document.layers
+ if layers then
+ for i=1,#layers do
+ local layer = layers[i]
+ if layer then
+ local tag = namespace .. gsub(layer," ",":")
+ local title = tag
+ if trace_links then
+ report_link("using layer %a",tag)
+ end
+ attributes.viewerlayers.define { -- also does some cleaning
+ tag = tag, -- todo: #3A or so
+ title = title,
+ visible = variables.start,
+ editable = variables.yes,
+ printable = variables.yes,
+ }
+ codeinjections.useviewerlayer(tag)
+ elseif trace_links then
+ report_link("broken layer, index %a",i)
+ end
+ end
+ end
+end
+
+-- It took a bit of puzzling and playing around to come to the following
+-- implementation. In the end it looks simple but as usual it takes a while
+-- to see what the specification (and implementation) boils down to. Lots of
+-- shared properties and such. The scaling took some trial and error as
+-- viewers differ. I had to extend some low level helpers to make it more
+-- comfortable. Hm, the specification is somewhat incomplete as some fields
+-- are permitted even if not mentioned so in the end we can share more code.
+--
+-- If all works ok, we can get rid of some copies which saves time and space.
+
+local commentlike = {
+ Text = "text",
+ FreeText = "freetext",
+ Line = "line",
+ Square = "shape",
+ Circle = "shape",
+ Polygon = "poly",
+ PolyLine = "poly",
+ Highlight = "markup",
+ Underline = "markup",
+ Squiggly = "markup",
+ StrikeOut = "markup",
+ Caret = "text",
+ Stamp = "stamp",
+ Ink = "ink",
+ Popup = "popup",
+}
+
+local function copyBS(v) -- dict can be shared
+ if v then
+ -- return pdfdictionary {
+ -- Type = copypdfconstant(V.Type),
+ -- W = copypdfnumber (V.W),
+ -- S = copypdfstring (V.S),
+ -- D = copypdfarray (V.D),
+ -- }
+ return copypdfdictionary(v)
+ end
+end
+
+local function copyBE(v) -- dict can be shared
+ if v then
+ -- return pdfdictionary {
+ -- S = copypdfstring(V.S),
+ -- I = copypdfnumber(V.I),
+ -- }
+ return copypdfdictionary(v)
+ end
+end
+
+local function copyBorder(v) -- dict can be shared
+ if v then
+ -- todo
+ return copypdfarray(v)
+ end
+end
+
+local function copyPopup(v,references)
+ if v then
+ local p = references[v]
+ if p then
+ return pdfreference(p)
+ end
+ end
+end
+
+local function copyParent(v,references)
+ if v then
+ local p = references[v]
+ if p then
+ return pdfreference(p)
+ end
+ end
+end
+
+local function copyIRT(v,references)
+ if v then
+ local p = references[v]
+ if p then
+ return pdfreference(p)
+ end
+ end
+end
+
+local function copyC(v)
+ if v then
+ -- todo: check color space
+ return pdfcopyarray(v)
+ end
+end
+
+local function finalizer(d,xscale,yscale,a_llx,a_ury)
+ local q = d.QuadPoints or d.Vertices or d.CL
+ if q then
+ return function()
+ local h, v = pdfgetpos() -- already scaled
+ for i=1,#q,2 do
+ q[i] = xscale * q[i] + (h*bpfactor - xscale * a_llx)
+ q[i+1] = yscale * q[i+1] + (v*bpfactor - yscale * a_ury)
+ end
+ return d()
+ end
+ end
+ q = d.InkList or d.Path
+ if q then
+ return function()
+ local h, v = pdfgetpos() -- already scaled
+ for i=1,#q do
+ local q = q[i]
+ for i=1,#q,2 do
+ q[i] = xscale * q[i] + (h*bpfactor - xscale * a_llx)
+ q[i+1] = yscale * q[i+1] + (v*bpfactor - yscale * a_ury)
+ end
+ end
+ return d()
+ end
+ end
+ return d()
+end
+
+local validstamps = {
+ Approved = true,
+ Experimental = true,
+ NotApproved = true,
+ AsIs = true,
+ Expired = true,
+ NotForPublicRelease = true,
+ Confidential = true,
+ Final = true,
+ Sold = true,
+ Departmental = true,
+ ForComment = true,
+ TopSecret = true,
+ Draft = true,
+ ForPublicRelease = true,
+}
+
+-- todo: we can use runtoks instead of steps
+
+local function validStamp(v)
+ local name = "Stamped" -- fallback
+ if v then
+ local ok = validstamps[v]
+ if ok then
+ name = ok
+ else
+ for k in next, validstamps do
+ if find(v,k.."$") then
+ name = k
+ validstamps[v] = k
+ break
+ end
+ end
+ end
+ end
+ -- we temporary return to \TEX:
+ context.predefinesymbol { name }
+ context.step()
+ -- beware, an error is not reported
+ return pdfconstant(name), codeinjections.analyzenormalsymbol(name)
+end
+
+local annotationflags = lpdf.flags.annotations
+
+local function copyF(v,lock) -- todo: bxor 24
+ if lock then
+ v = bor(v or 0,annotationflags.ReadOnly + annotationflags.Locked + annotationflags.LockedContents)
+ end
+ if v then
+ return pdfcopyinteger(v)
+ end
+end
+
+-- Speed is not really an issue so we don't optimize this code too much. In the end (after
+-- testing we end up with less code that we started with.
+
+function codeinjections.mergecomments(specification)
+ local specification, fullname, document = validdocument(specification)
+ if not document then
+ return ""
+ end
+ local pagenumber = specification.page or 1
+ local pagedata = document.pages[pagenumber]
+ local annotations = pagedata and pagedata.Annots
+ if annotations and #annotations > 0 then
+ local llx, lly, urx, ury, width, height, xscale, yscale = getmediasize(specification,pagedata,xscale,yscale)
+ initializelayer(height,width)
+ --
+ local lockflags = specification.lock -- todo: proper parameter
+ local references = { }
+ local usedpopups = { }
+ for i=1,#annotations do
+ local annotation = annotations[i]
+ if annotation then
+ local subtype = annotation.Subtype
+ if commentlike[subtype] then
+ references[annotation] = pdfreserveobject()
+ local p = annotation.Popup
+ if p then
+ usedpopups[p] = true
+ end
+ end
+ end
+ end
+ --
+ for i=1,#annotations do
+ -- we keep the order
+ local annotation = annotations[i]
+ if annotation then
+ local reference = references[annotation]
+ if reference then
+ local subtype = annotation.Subtype
+ local kind = commentlike[subtype]
+ if kind ~= "popup" or usedpopups[annotation] then
+ local x, y, w, h, a_llx, a_lly, a_urx, a_ury = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_comment)
+ if x then
+ local voffset = h
+ local dictionary = pdfdictionary {
+ Subtype = pdfconstant (subtype),
+ -- common (skipped: P AP AS OC AF BM StructParent)
+ Contents = pdfcopyunicode(annotation.Contents),
+ NM = pdfcopystring (annotation.NM),
+ M = pdfcopystring (annotation.M),
+ F = copyF (annotation.F,lockflags),
+ C = copyC (annotation.C),
+ ca = pdfcopynumber (annotation.ca),
+ CA = pdfcopynumber (annotation.CA),
+ Lang = pdfcopystring (annotation.Lang),
+ -- also common
+ CreationDate = pdfcopystring (annotation.CreationDate),
+ T = pdfcopyunicode(annotation.T),
+ Subj = pdfcopyunicode(annotation.Subj),
+ -- border
+ Border = pdfcopyarray (annotation.Border),
+ BS = copyBS (annotation.BS),
+ BE = copyBE (annotation.BE),
+ -- sort of common
+ Popup = copyPopup (annotation.Popup,references),
+ RC = pdfcopyunicode(annotation.RC) -- string or stream
+ }
+ if kind == "markup" then
+ dictionary.IRT = copyIRT (annotation.IRT,references)
+ dictionary.RT = pdfconstant (annotation.RT)
+ dictionary.IT = pdfcopyconstant (annotation.IT)
+ dictionary.QuadPoints = pdfcopyarray (annotation.QuadPoints)
+ -- dictionary.RD = pdfcopyarray (annotation.RD)
+ elseif kind == "text" then
+ -- somehow F fails to view : /F 24 : bit4=nozoom bit5=norotate
+ dictionary.F = nil
+ dictionary.Open = pdfcopyboolean (annotation.Open)
+ dictionary.Name = pdfcopyunicode (annotation.Name)
+ dictionary.State = pdfcopystring (annotation.State)
+ dictionary.StateModel = pdfcopystring (annotation.StateModel)
+ dictionary.IT = pdfcopyconstant (annotation.IT)
+ dictionary.QuadPoints = pdfcopyarray (annotation.QuadPoints)
+ dictionary.RD = pdfcopyarray (annotation.RD) -- caret
+ dictionary.Sy = pdfcopyconstant (annotation.Sy) -- caret
+ voffset = 0
+ elseif kind == "freetext" then
+ dictionary.DA = pdfcopystring (annotation.DA)
+ dictionary.Q = pdfcopyinteger (annotation.Q)
+ dictionary.DS = pdfcopystring (annotation.DS)
+ dictionary.CL = pdfcopyarray (annotation.CL)
+ dictionary.IT = pdfcopyconstant (annotation.IT)
+ dictionary.LE = pdfcopyconstant (annotation.LE)
+ -- dictionary.RC = pdfcopystring (annotation.RC)
+ elseif kind == "line" then
+ dictionary.LE = pdfcopyarray (annotation.LE)
+ dictionary.IC = pdfcopyarray (annotation.IC)
+ dictionary.LL = pdfcopynumber (annotation.LL)
+ dictionary.LLE = pdfcopynumber (annotation.LLE)
+ dictionary.Cap = pdfcopyboolean (annotation.Cap)
+ dictionary.IT = pdfcopyconstant (annotation.IT)
+ dictionary.LLO = pdfcopynumber (annotation.LLO)
+ dictionary.CP = pdfcopyconstant (annotation.CP)
+ dictionary.Measure = pdfcopydictionary(annotation.Measure) -- names
+ dictionary.CO = pdfcopyarray (annotation.CO)
+ voffset = 0
+ elseif kind == "shape" then
+ dictionary.IC = pdfcopyarray (annotation.IC)
+ -- dictionary.RD = pdfcopyarray (annotation.RD)
+ voffset = 0
+ elseif kind == "stamp" then
+ local name, appearance = validStamp(annotation.Name)
+ dictionary.Name = name
+ dictionary.AP = appearance
+ voffset = 0
+ elseif kind == "ink" then
+ dictionary.InkList = pdfcopyarray (annotation.InkList)
+ elseif kind == "poly" then
+ dictionary.Vertices = pdfcopyarray (annotation.Vertices)
+ -- dictionary.LE = pdfcopyarray (annotation.LE) -- todo: names in array
+ dictionary.IC = pdfcopyarray (annotation.IC)
+ dictionary.IT = pdfcopyconstant (annotation.IT)
+ dictionary.Measure = pdfcopydictionary(annotation.Measure)
+ dictionary.Path = pdfcopyarray (annotation.Path)
+ -- dictionary.RD = pdfcopyarray (annotation.RD)
+ elseif kind == "popup" then
+ dictionary.Open = pdfcopyboolean (annotation.Open)
+ dictionary.Parent = copyParent (annotation.Parent,references)
+ voffset = 0
+ end
+ if dictionary then
+ local locationspec = {
+ x = x .. "bp",
+ y = y .. "bp",
+ voffset = voffset .. "bp",
+ preset = "leftbottom",
+ }
+ local finalize = finalizer(dictionary,xscale,yscale,a_llx,a_ury)
+ context.setlayer(layerspec,locationspec,function()
+ context(hpack_node(nodeinjections.annotation(w/bpfactor,h/bpfactor,0,finalize,reference)))
+ end)
+ end
end
- attributes.viewerlayers.define { -- also does some cleaning
- tag = tag, -- todo: #3A or so
- title = title,
- visible = variables.start,
- editable = variables.yes,
- printable = variables.yes,
- }
- codeinjections.useviewerlayer(tag)
- elseif trace_links then
- report_link("broken layer, index %a",i)
+ else
+ -- report_comment("skipping annotation, index %a",i)
end
end
+ elseif trace_comments then
+ report_comment("broken annotation, index %a",i)
end
end
end
+ return namespace
end
--- new: for taco
+local widgetflags = lpdf.flags.widgets
+
+local function flagstoset(flag,flags)
+ local t = { }
+ if flags then
+ for k, v in next, flags do
+ if band(flag,v) ~= 0 then
+ t[k] = true
+ end
+ end
+ end
+ return t
+end
+
+-- BS : border style dict
+-- R : rotation 0 90 180 270
+-- BG : background array
+-- CA : caption string
+-- RC : roll over caption
+-- AC : down caption
+-- I/RI/IX : icon streams
+-- IF : fit dictionary
+-- TP : text position number
+
+-- Opt : array of texts
+-- TI : top index
+
+-- V : value
+-- DV : default value
+-- DS : default string
+-- RV : rich
+-- Q : quadding (0=left 1=middle 2=right)
+
+function codeinjections.mergefields(specification)
+ local specification, fullname, document = validdocument(specification)
+ if not document then
+ return ""
+ end
+ local pagenumber = specification.page or 1
+ local pagedata = document.pages[pagenumber]
+ local annotations = pagedata and pagedata.Annots
+ if annotations and #annotations > 0 then
+ local llx, lly, urx, ury, width, height, xscale, yscale = getmediasize(specification,pagedata,xscale,yscale)
+ initializelayer(height,width)
+ --
+ for i=1,#annotations do
+ -- we keep the order
+ local annotation = annotations[i]
+ if annotation then
+ local subtype = annotation.Subtype
+ if subtype == "Widget" then
+ local parent = annotation.Parent or { }
+ local name = annotation.T or parent.T
+ local what = annotation.FT or parent.FT
+ if name and what then
+ local x, y, w, h, a_llx, a_lly, a_urx, a_ury = getdimensions(annotation,llx,lly,xscale,yscale,width,height,report_field)
+ if x then
+ x = x .. "bp"
+ y = y .. "bp"
+ local W, H = w, h
+ w = w .. "bp"
+ h = h .. "bp"
+ if trace_fields then
+ report_field("field %a, type %a, dx %s, dy %s, wd %s, ht %s",name,what,x,y,w,h)
+ end
+ local locationspec = {
+ x = x,
+ y = y,
+ preset = "leftbottom",
+ }
+ --
+ local aflags = flagstoset(annotation.F or parent.F, annotationflags)
+ local wflags = flagstoset(annotation.Ff or parent.Ff, widgetflags)
+ if what == "Tx" then
+ -- DA DV F FT MaxLen MK Q T V | AA OC
+ if wflags.MultiLine then
+ wflags.MultiLine = nil
+ what = "text"
+ else
+ what = "line"
+ end
+ -- via context
+ local fieldspec = {
+ width = w,
+ height = h,
+ offset = variables.overlay,
+ frame = trace_links and variables.on or variables.off,
+ n = annotation.MaxLen or (parent and parent.MaxLen),
+ type = what,
+ option = concat(merged(aflags,wflags),","),
+ }
+ context.setlayer (layerspec,locationspec,function()
+ context.definefieldbody ( { name } , fieldspec )
+ context.fieldbody ( { name } )
+ end)
+ --
+ elseif what == "Btn" then
+ if wflags.Radio or wflags.RadiosInUnison then
+ -- AP AS DA F Ff FT H MK T V | AA OC
+ wflags.Radio = nil
+ wflags.RadiosInUnison = nil
+ what = "radio"
+ elseif wflags.PushButton then
+ -- AP DA F Ff FT H MK T | AA OC
+ --
+ -- Push buttons only have an appearance and some associated
+ -- actions so they are not worth copying.
+ --
+ wflags.PushButton = nil
+ what = "push"
+ else
+ -- AP AS DA F Ff FT H MK T V | OC AA
+ what = "check"
+ -- direct
+ local AP = annotation.AP or (parent and parent.AP)
+ if AP then
+ local a = document.__xrefs__[AP]
+ if a and pdfe.copyappearance then
+ local o = pdfe.copyappearance(document,a)
+ if o then
+ AP = pdfreference(o)
+ end
+ end
+ end
+ local dictionary = pdfdictionary {
+ Subtype = pdfconstant("Widget"),
+ FT = pdfconstant("Btn"),
+ T = pdfcopyunicode(annotation.T or parent.T),
+ F = pdfcopyinteger(annotation.F or parent.F),
+ Ff = pdfcopyinteger(annotation.Ff or parent.Ff),
+ AS = pdfcopyconstant(annotation.AS or (parent and parent.AS)),
+ AP = AP and pdfreference(AP),
+ }
+ local finalize = dictionary()
+ context.setlayer(layerspec,locationspec,function()
+ context(hpack_node(nodeinjections.annotation(W/bpfactor,H/bpfactor,0,finalize)))
+ end)
+ --
+ end
+ elseif what == "Ch" then
+ -- F Ff FT Opt T | AA OC (rest follows)
+ if wflags.PopUp then
+ wflags.PopUp = nil
+ if wflags.Edit then
+ wflags.Edit = nil
+ what = "combo"
+ else
+ what = "popup"
+ end
+ else
+ what = "choice"
+ end
+ elseif what == "Sig" then
+ what = "signature"
+ else
+ what = nil
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
-- Beware, bookmarks can be in pdfdoc encoding or in unicode. However, in mkiv we
-- write out the strings in unicode (hex). When we read them in, we check for a bom
@@ -337,7 +882,7 @@ function codeinjections.getbookmarks(filename)
local outlines = document.Catalog.Outlines
local pages = document.pages
- local nofpages = pages.n -- we need to access once in order to initialize
+ local nofpages = document.nofpages
local destinations = document.destinations
-- I need to check this destination analyzer with the one in annotations .. best share
@@ -359,7 +904,7 @@ function codeinjections.getbookmarks(filename)
entry.realpage = pagedata.number
end
elseif kind == "table" then
- local pageref = destination.n
+ local pageref = #destination
if pageref then
local pagedata = pages[pageref]
if pagedata then
@@ -367,8 +912,8 @@ function codeinjections.getbookmarks(filename)
end
end
end
- else
- -- maybe
+ -- elseif subtype then
+ -- report("unsupported bookmark action %a",subtype)
end
else
local destination = current.Dest
@@ -383,6 +928,8 @@ function codeinjections.getbookmarks(filename)
local pagedata = destination and destination[1]
if pagedata and pagedata.Type == "Page" then
entry.realpage = pagedata.number
+ -- else
+ -- report("unsupported bookmark destination (no page)")
end
end
end
@@ -471,16 +1018,6 @@ function codeinjections.mergebookmarks(specification)
end
end
--- placeholders:
-
-function codeinjections.mergecomments(specification)
- report_comment("unfinished experimental code, not used yet")
-end
-
-function codeinjections.mergefields(specification)
- report_field("unfinished experimental code, not used yet")
-end
-
-- A bit more than a placeholder but in the same perspective as
-- inclusion of comments and fields:
--
@@ -501,7 +1038,7 @@ function codeinjections.getinfo(specification)
local catalog = pdffile.Catalog
local info = pdffile.Info
local pages = pdffile.pages
- local nofpages = pages.n
+ local nofpages = pdffile.nofpages
if metadata then
local m = catalog.Metadata
if m then
@@ -525,10 +1062,8 @@ function codeinjections.getinfo(specification)
local media = nobox
local page = pages[pagenumber]
if page then
- crop = page.CropBox or nobox
- media = page.MediaBox or crop or nobox
- crop.n = nil -- nicer
- media.n = nil -- nicer
+ crop = page.CropBox or nobox
+ media = page.MediaBox or crop or nobox
end
local bbox = crop or media or nobox
return {
diff --git a/tex/context/base/mkiv/lpdf-epd.lua b/tex/context/base/mkiv/lpdf-epd.lua
index cf02b5a22..86aa6f294 100644
--- a/tex/context/base/mkiv/lpdf-epd.lua
+++ b/tex/context/base/mkiv/lpdf-epd.lua
@@ -32,7 +32,7 @@ if not modules then modules = { } end modules ['lpdf-epd'] = {
-- already was unicode).
local setmetatable, rawset, rawget, type, next = setmetatable, rawset, rawget, type, next
-local tostring, tonumber = tostring, tonumber
+local tostring, tonumber, unpack = tostring, tonumber, unpack
local lower, match, char, byte, find = string.lower, string.match, string.char, string.byte, string.find
local abs = math.abs
local concat = table.concat
@@ -67,13 +67,27 @@ local xref = registry["epdf.XRef"]
local catalog = registry["epdf.Catalog"]
local pdfdoc = registry["epdf.PDFDoc"]
+if not (object and dictionary and array and xref and catalog and pdfdoc) then
+ logs.report("fatal error","invalid pdf inclusion library (%s)",1)
+ os.exit()
+end
+
local openPDF = epdf.open
+local getMajorVersion = pdfdoc.getPDFMajorVersion
+local getMinorVersion = pdfdoc.getPDFMinorVersion
+local getXRef = pdfdoc.getXRef
+local getRawCatalog = pdfdoc.getCatalog
+
+if not (openPDF and getMajorVersion and getMinorVersion and getXRef and getRawCatalog) then
+ logs.report("fatal error","invalid pdf inclusion library (%s)",2)
+ os.exit()
+end
+
local getDict = object.getDict
local getArray = object.getArray
local getReal = object.getReal
local getInt = object.getInt
-local getNum = object.getNum
local getString = object.getString
local getBool = object.getBool
local getName = object.getName
@@ -81,59 +95,81 @@ local getRef = object.getRef
local getRefNum = object.getRefNum
local getType = object.getType
-local getTypeName = object.getTypeName
+
+if not (getDict and getArray and getReal and getInt and getString and getBool and getName and getRef and getRefNum and getType) then
+ logs.report("fatal error","invalid pdf inclusion library (%s)",3)
+ os.exit()
+end
local streamReset = object.streamReset
local streamGetDict = object.streamGetDict
local streamGetChar = object.streamGetChar
+local streamGetAll = object.streamGetAll
+
+if not (streamReset and streamGetDict and streamGetChar) then
+ logs.report("fatal error","invalid pdf inclusion library (%s)",3)
+ os.exit()
+end
local dictGetLength = dictionary.getLength
local dictGetVal = dictionary.getVal
local dictGetValNF = dictionary.getValNF
local dictGetKey = dictionary.getKey
+if not (dictGetLength and dictGetVal and dictGetValNF and dictGetKey) then
+ logs.report("fatal error","invalid pdf inclusion library (%s)",4)
+ os.exit()
+end
+
local arrayGetLength = array.getLength
local arrayGetNF = array.getNF
local arrayGet = array.get
+if not (arrayGetLength and arrayGetNF and arrayGet) then
+ logs.report("fatal error","invalid pdf inclusion library (%s)",5)
+ os.exit()
+end
+
-- these are kind of weird as they can't be accessed by (root) object
local getNumPages = catalog.getNumPages
local getPageRef = catalog.getPageRef
-local getXRef = pdfdoc.getXRef
-local getRawCatalog = pdfdoc.getCatalog
-
local fetch = xref.fetch
local getCatalog = xref.getCatalog
local getDocInfo = xref.getDocInfo
+if not (getNumPages and getPageRef and fetch and getCatalog and getDocInfo) then
+ logs.report("fatal error","invalid pdf inclusion library (%s)",6)
+ os.exit()
+end
+
-- we're done with library shortcuts
-local report_epdf = logs.reporter("epdf")
-
-local typenames = { [0] =
- "boolean",
- "integer",
- "real",
- "string",
- "name",
- "null",
- "array",
- "dictionary",
- "stream",
- "ref",
- "cmd",
- "error",
- "eof",
- "none",
- "integer64",
+local typenames = { [0] =
+ "boolean",
+ "integer",
+ "real",
+ "string",
+ "name",
+ "null",
+ "array",
+ "dictionary",
+ "stream",
+ "ref",
+ "cmd",
+ "error",
+ "eof",
+ "none",
+ "integer64",
}
-local typenumbers = table.swapped(typenames)
+local typenumbers = table.swapped(typenames)
+
+local null_object_code = typenumbers.null
+local ref_object_code = typenumbers.ref
-local null_code = typenumbers.null
-local ref_code = typenumbers.ref
+local report_epdf = logs.reporter("epdf")
local function fatal_error(...)
report_epdf(...)
@@ -206,32 +242,30 @@ local function prepare(document,d,t,n,k,mt,flags)
if v then
local r = dictGetValNF(d,i)
local kind = getType(v)
- if kind == null_code then
+ if kind == null_object_code then
-- ignore
- else
+ elseif kind then
local key = dictGetKey(d,i)
- if kind then
- if r and getType(r) == ref_code then
- local objnum = getRefNum(r)
- local cached = document.__cache__[objnum]
- if not cached then
- cached = checked_access[kind](v,document,objnum,mt)
- if cached then
- document.__cache__[objnum] = cached
- document.__xrefs__[cached] = objnum
- end
- end
- t[key] = cached
- else
- local v, flag = checked_access[kind](v,document)
- t[key] = v
- if flag and flags then
- flags[key] = flag -- flags
+ if r and getType(r) == ref_object_code then
+ local objnum = getRefNum(r)
+ local cached = document.__cache__[objnum]
+ if not cached then
+ cached = checked_access[kind](v,document,objnum,mt)
+ if cached then
+ document.__cache__[objnum] = cached
+ document.__xrefs__[cached] = objnum
end
end
+ t[key] = cached
else
- report_epdf("warning: nil value for key %a in dictionary",key)
+ local v, flag = checked_access[kind](v,document)
+ t[key] = v
+ if flag and flags then
+ flags[key] = flag -- flags
+ end
end
+ else
+ report_epdf("warning: nil value for key %a in dictionary",key)
end
else
fatal_error("error: invalid value at index %a in dictionary of %a",i,document.filename)
@@ -245,6 +279,42 @@ local function prepare(document,d,t,n,k,mt,flags)
return t[k]
end
+-- local function prepare(document,d,t,n,k,mt,flags)
+-- for i=1,n do
+-- local v = dictGetValNF(d,i)
+-- if v then
+-- local key = dictGetKey(d,i)
+-- local kind = getType(v)
+-- if kind == ref_object_code then
+-- local objnum = getRefNum(v)
+-- local cached = document.__cache__[objnum]
+-- if not cached then
+-- local v = dictGetVal(d,i)
+-- local kind = getType(v)
+-- cached = checked_access[kind](v,document,objnum,mt)
+-- if cached then
+-- document.__cache__[objnum] = cached
+-- document.__xrefs__[cached] = objnum
+-- end
+-- end
+-- t[key] = cached
+-- else
+-- local v, flag = checked_access[kind](v,document)
+-- t[key] = v
+-- if flag and flags then
+-- flags[key] = flag -- flags
+-- end
+-- end
+-- end
+-- end
+-- if mt then
+-- setmetatable(t,mt)
+-- else
+-- getmetatable(t).__index = nil
+-- end
+-- return t[k]
+-- end
+
local function some_dictionary(d,document)
local n = d and dictGetLength(d) or 0
if n > 0 then
@@ -293,11 +363,11 @@ local function prepare(document,a,t,n,k)
local v = arrayGet(a,i)
if v then
local kind = getType(v)
- if kind == null_code then
+ if kind == null_object_code then
-- ignore
elseif kind then
local r = arrayGetNF(a,i)
- if r and getType(r) == ref_code then
+ if r and getType(r) == ref_object_code then
local objnum = getRefNum(r)
local cached = document.__cache__[objnum]
if not cached then
@@ -326,6 +396,37 @@ local function prepare(document,a,t,n,k)
end
end
+-- local function prepare(document,a,t,n,k)
+-- for i=1,n do
+-- local v = arrayGetNF(a,i)
+-- if v then
+-- local kind = getType(v)
+-- if kind == ref_object_code then
+-- local objnum = getRefNum(v)
+-- local cached = document.__cache__[objnum]
+-- if not cached then
+-- local v = arrayGet(a,i)
+-- local kind = getType(v)
+-- cached = checked_access[kind](v,document,objnum)
+-- document.__cache__[objnum] = cached
+-- document.__xrefs__[cached] = objnum
+-- end
+-- t[i] = cached
+-- else
+-- t[i] = checked_access[kind](v,document)
+-- end
+-- end
+-- end
+-- local m = getmetatable(t)
+-- if m then
+-- m.__index = nil
+-- m.__len = nil
+-- end
+-- if k then
+-- return t[k]
+-- end
+-- end
+
local function some_array(a,document)
local n = a and arrayGetLength(a) or 0
if n > 0 then
@@ -376,23 +477,53 @@ end
-- todo: collect chunks
-local function streamaccess(s,_,what)
- if not what or what == "all" or what == "*all" then
- local t, n = { }, 0
- streamReset(s)
+-- local function streamaccess(s,_,what)
+-- if not what or what == "all" or what == "*all" then
+-- local t, n = { }, 0
+-- streamReset(s)
+-- while true do
+-- local c = streamGetChar(s)
+-- if c < 0 then
+-- break
+-- else
+-- n = n + 1
+-- t[n] = char(c)
+-- end
+-- end
+-- return concat(t,"",1,n)
+-- end
+-- end
+
+local function getstream(s)
+ streamReset(s)
+ if streamGetAll then
+ return streamGetAll(s)
+ else
+ local t, b, n = { }, { }, 0
while true do
local c = streamGetChar(s)
if c < 0 then
break
else
n = n + 1
- t[n] = char(c)
+ b[n] = c
+ end
+ if n == 2000 then
+ t[#t+1] = char(unpack(b,1,n))
+ n = 1
end
end
+ t[#t+1] = char(unpack(b,1,n))
return concat(t)
end
end
+local function streamaccess(s,_,what)
+ if not what or what == "all" or what == "*all" then
+ return getstream(s)
+ end
+end
+
local function get_stream(d,document)
if d then
streamReset(d)
@@ -562,16 +693,19 @@ end
-- with but it won't win a beauty contest.
local function getpages(document,Catalog)
- local __data__ = document.__data__
- local __xrefs__ = document.__xrefs__
- local __cache__ = document.__cache__
- local __xref__ = document.__xref__
+ local __data__ = document.__data__
+ local __xrefs__ = document.__xrefs__
+ local __cache__ = document.__cache__
+ local __xref__ = document.__xref__
+ --
+ local rawcatalog = getRawCatalog(__data__)
+ local nofpages = getNumPages(rawcatalog)
--
- local rawcatalog = getRawCatalog(__data__)
- local nofpages = getNumPages(rawcatalog)
+ local majorversion = getMajorVersion(__data__)
+ local minorversion = getMinorVersion(__data__)
--
- local pages = { }
- local metatable = { __index = Catalog.Pages } -- somewhat empty
+ local pages = { }
+ local metatable = { __index = Catalog.Pages } -- somewhat empty
--
for pagenumber=1,nofpages do
local pagereference = getPageRef(rawcatalog,pagenumber).num
@@ -580,6 +714,7 @@ local function getpages(document,Catalog)
if pagedata then
-- rawset(pagedata,"number",pagenumber)
pagedata.number = pagenumber
+ pagedata.object = pageobject
pages[pagenumber] = pagedata
__xrefs__[pagedata] = pagereference
__cache__[pagereference] = pagedata
@@ -590,7 +725,10 @@ local function getpages(document,Catalog)
--
pages.n = nofpages
--
- document.pages = pages
+ document.pages = pages
+ document.majorversion = majorversion
+ document.minorversion = minorversion
+ --
return pages
end
@@ -637,6 +775,8 @@ function lpdf_epdf.load(filename)
document.Catalog = some_dictionary(getDict(getCatalog(__xref__)),document)
document.Info = some_dictionary(getDict(getDocInfo(__xref__)),document)
setmetatableindex(document,resolve)
+ --
+ document.nofpages = getNumPages(getRawCatalog(__data__))
else
document = false
end
@@ -735,14 +875,14 @@ local fromunicode = (
P(1)
)^1 * Carg(1)
-local function analyzefonts(document,resources) -- unfinished
+local function analyzefonts(document,resources) -- unfinished, see mtx-pdf for better code
local fonts = document.__fonts__
if resources then
local fontlist = resources.Font
if fontlist then
for id, data in expanded(fontlist) do
if not fonts[id] then
- -- a quck hack ... I will look into it more detail if I find a real
+ -- a quick hack ... I will look into it more detail if I find a real
-- -application for it
local tounicode = data.ToUnicode()
if tounicode then
@@ -836,7 +976,7 @@ function lpdf_epdf.getpagecontent(document,pagenumber)
end
--- This is also an experiment. When I really neet it I can improve it, fo rinstance
+-- This is also an experiment. When I really need it I can improve it, for instance
-- with proper position calculating. It might be usefull for some search or so.
local softhyphen = utfchar(0xAD) .. "$"
@@ -925,3 +1065,249 @@ end
-- local destination = document.__data__:findDest(name)
-- return destination and destination.number
-- end
+
+-- This is experimental code that we need for testing the transition from
+-- poppler to a new lightweight library. Don't rely on this code to remain
+-- as it is now. Interesting is that performance of this variant is the same
+-- as the natural page includer.
+
+if img then do
+
+ local copydictionary = nil
+ local copyarray = nil
+
+ local ref_object_code = typenumbers.ref
+ local boolean_object_code = typenumbers.boolean
+ local integer_object_code = typenumbers.integer
+ local real_object_code = typenumbers.real
+ local string_object_code = typenumbers.string
+ local name_object_code = typenumbers.name
+ local null_object_code = typenumbers.null
+ local array_object_code = typenumbers.array
+ local dictionary_object_code = typenumbers.dictionary
+ local stream_object_code = typenumbers.stream
+ local cmd_object_code = typenumbers.cmd
+
+ local pdfreserveobject = lpdf.reserveobject
+ local pdfflushobject = lpdf.flushobject
+ local pdfflushstreamobject = lpdf.flushstreamobject
+ local pdfreference = lpdf.reference
+ local pdfconstant = lpdf.constant
+ local pdfarray = lpdf.array
+ local pdfdictionary = lpdf.dictionary
+ local pdfunicode = lpdf.unicode
+ local pdfstring = lpdf.string
+ local pdfnull = lpdf.null
+
+ local report = logs.reporter("backend","xobjects")
+
+ local factor = 65536 / (7200/7227) -- 1/number.dimenfactors.bp
+
+ local createimage = images.create
+
+ local function scaledbbox(b)
+ return { b[1]*factor, b[2]*factor, b[3]*factor, b[4]*factor }
+ end
+
+ local function copyobject(xref,copied,kind,r,v)
+ if kind == null_object_code then
+ return pdfnull()
+ elseif r and getType(r) == ref_object_code then
+ local objnum = getRefNum(r)
+ local r = copied[objnum]
+ if r then
+ -- report("%s object %i is reused",kind,objnum)
+ else
+ local o
+ r = pdfreserveobject()
+ copied[objnum] = r
+ if kind == array_object_code then
+ local a = copyarray(xref,copied,fetch(xref,objnum,0))
+ pdfflushobject(r,tostring(a))
+ elseif kind == dictionary_object_code then
+ local d = copydictionary(xref,copied,fetch(xref,objnum,0))
+ pdfflushobject(r,tostring(d))
+ elseif kind == stream_object_code then
+ local f = fetch(xref,objnum,0)
+ local d = copydictionary(xref,copied,false,streamGetDict(f))
+ local s = getstream(f)
+ --
+ d.Filter = nil
+ d.Length = nil
+ d.DecodeParms = nil
+ d.DL = nil
+ --
+ pdfflushstreamobject(s,d,true,r)
+ else
+ report("reference not done: %s", kind)
+ end
+ end
+ return pdfreference(r)
+ elseif kind == array_object_code then
+ return copyarray(xref,copied,v)
+ elseif kind == dictionary_object_code then
+ return copydictionary(xref,copied,v)
+ elseif kind == integer_object_code then
+ return getInt(v)
+ elseif kind == real_object_code then
+ return getReal(v)
+ elseif kind == name_object_code then
+ return pdfconstant(getName(v))
+ elseif kind == string_object_code then
+ local s = getString(v)
+ if not s or s == "" then
+ return ""
+ end
+ local u = lpegmatch(u_pattern,s)
+ if u then
+ return pdfunicode(s)
+ end
+ return pdfstring(s)
+ elseif kind == boolean_object_code then
+ return getBool(v)
+ elseif kind == stream_object_code then
+ -- hm ...
+ return getStream(v)
+ else
+ report("object not done: %s", kind)
+ end
+ end
+
+ copyarray = function (xref,copied,object)
+ local a = getArray(object)
+ local n = a and arrayGetLength(a) or 0
+ if n > 0 then
+ local target = pdfarray()
+ for i=1,n do
+ local v = arrayGet(a,i)
+ if v then
+ local kind = getType(v)
+ local r = arrayGetNF(a,i)
+ target[i] = copyobject(xref,copied,kind,r,v)
+ end
+ end
+ return target
+ end
+ end
+
+ copydictionary = function (xref,copied,object,d)
+ local d = d or getDict(object)
+ local n = d and dictGetLength(d) or 0
+ if n > 0 then
+ local target = pdfdictionary()
+ for i=1,n do
+ local v = dictGetVal(d,i)
+ if v then
+ local kind = getType(v)
+ local key = dictGetKey(d,i)
+ local r = dictGetValNF(d,i)
+ target[key] = copyobject(xref,copied,kind,r,v)
+ end
+ end
+ return target
+ end
+ end
+
+ local function copy_resources(pdfdoc,xref,copied,pagedata)
+ local object = pagedata.object
+ if object then
+ local d = getDict(object)
+ local n = d and dictGetLength(d) or 0
+ for i=1,n do
+ local k = dictGetKey(d,i)
+ if v and k == "Resources" then
+ local v = dictGetVal(d,i)
+ local kind = getType(v)
+ local r = dictGetValNF(d,i)
+ return copyobject(xref,copied,kind,r,v)
+ end
+ end
+ end
+ end
+
+ local function openpdf(filename)
+ local pdfdoc = lpdf_epdf.load(filename)
+ if pdfdoc then
+ pdfdoc.__copied__ = pdfdoc.__copied__ or { }
+ pdfdoc.filename = filename
+ return pdfdoc
+ end
+ end
+
+ local function closepdf(pdfdoc)
+ if pdfdoc then
+ lpdf_epdf.unload(pdfdoc.filename)
+ end
+ end
+
+ local function querypdf(pdfdoc,pagenumber)
+ if pdfdoc then
+ if not pagenumber then
+ pagenumber = 1
+ end
+ local root = pdfdoc.Catalog
+ local page = pdfdoc.pages[pagenumber]
+ if page then
+ local mediabox = page.MediaBox or { 0, 0, 0, 0 }
+ local cropbox = page.CropBox or mediabox
+ return {
+ filename = pdfdoc.filename,
+ pagenumber = pagenumber,
+ nofpages = pdfdoc.nofpages,
+ boundingbox = scaledbbox(cropbox),
+ cropbox = cropbox,
+ mediabox = mediabox,
+ bleedbox = page.BleedBox or cropbox,
+ trimbox = page.TrimBox or cropbox,
+ artbox = page.ArtBox or cropbox,
+ }
+ end
+ end
+ end
+
+ local function copypage(pdfdoc,pagenumber,attributes)
+ if pdfdoc then
+ local root = pdfdoc.Catalog
+ local page = pdfdoc.pages[pagenumber or 1]
+ local pageinfo = querypdf(pdfdoc,pagenumber)
+ local contents = page.Contents
+ local xref = pdfdoc.__xref__
+ local copied = pdfdoc.__copied__
+ --
+ local xobject = pdfdictionary {
+ Type = pdfconstant("XObject"),
+ Subtype = pdfconstant("Form"),
+ -- image attributes
+ FormType = 1,
+ BBox = pageinfo.cropbox,
+ -- Metadata = copy(xref,copied,root,"Metadata"),
+ -- Group = copy(xref,copied,page,"Group"),
+ -- LastModified = copy(xref,copied,page,"LastModified"),
+ -- Metadata = copy(xref,copied,page,"Metadata"),
+ -- PieceInfo = copy(xref,copied,page,"PieceInfo"),
+ Resources = copy_resources(pdfdoc,xref,copied,page),
+ -- SeparationInfo = copy(xref,copied,page,"SeparationInfo"),
+ }
+ if attributes then
+ for k, v in next, expand(attributes) do
+ page[k] = v -- maybe nested
+ end
+ end
+ return createimage {
+ bbox = pageinfo.boundingbox,
+ stream = contents(),
+ attr = xobject(),
+ }
+ end
+ end
+
+ -- todo: codeinjections
+
+ lpdf_epdf.image = {
+ open = openpdf,
+ close = closepdf,
+ query = querypdf,
+ copy = copypage,
+ }
+
+end end
diff --git a/tex/context/base/mkiv/lpdf-fld.lua b/tex/context/base/mkiv/lpdf-fld.lua
index 73de5eaf6..983be508f 100644
--- a/tex/context/base/mkiv/lpdf-fld.lua
+++ b/tex/context/base/mkiv/lpdf-fld.lua
@@ -103,7 +103,7 @@ local pdf_tx = pdfconstant("Tx")
local pdf_sig = pdfconstant("Sig")
local pdf_ch = pdfconstant("Ch")
local pdf_btn = pdfconstant("Btn")
------ pdf_yes = pdfconstant("Yes")
+local pdf_yes = pdfconstant("Yes")
local pdf_off = pdfconstant("Off")
local pdf_p = pdfconstant("P") -- None Invert Outline Push
local pdf_n = pdfconstant("N") -- None Invert Outline Push
@@ -341,10 +341,10 @@ local function fieldsurrounding(specification)
alternative, a = "tf", s.tf
end
local tag = fontstyle .. fontalternative
- fontsize = todimen(fontsize)
- fontsize = fontsize and (bpfactor * fontsize) or 12
+ fontsize = todimen(fontsize)
+ fontsize = fontsize and (bpfactor * fontsize) or 12
fontraise = 0.1 * fontsize -- todo: figure out what the natural one is and compensate for strutdp
- local fontcode = formatters["%0.4f Tf %0.4f Ts"](fontsize,fontraise)
+ local fontcode = formatters["%0.4F Tf %0.4F Ts"](fontsize,fontraise)
-- we could test for colorvalue being 1 (black) and omit it then
local colorcode = pdfcolor(3,colorvalue) -- we force an rgb color space
if trace_fields then
@@ -360,14 +360,16 @@ local function fieldsurrounding(specification)
return tostring(stream)
end
+-- Can we use any font?
+
codeinjections.fieldsurrounding = fieldsurrounding
local function registerfonts()
if next(usedfonts) then
checkpdfdocencoding() -- already done
- local d = pdfdictionary()
- local pdffonttype, pdffontsubtype = pdfconstant("Font"), pdfconstant("Type1")
- -- for tag, name in next, usedfonts do
+ local pdffontlist = pdfdictionary()
+ local pdffonttype = pdfconstant("Font")
+ local pdffontsubtype = pdfconstant("Type1")
for tag, name in sortedhash(usedfonts) do
local f = pdfdictionary {
Type = pdffonttype,
@@ -376,9 +378,9 @@ local function registerfonts()
BaseFont = pdfconstant(name),
Encoding = pdfdocencodingvector,
}
- d[tag] = pdfreference(pdfflushobject(f))
+ pdffontlist[tag] = pdfreference(pdfflushobject(f))
end
- return d
+ return pdffontlist
end
end
@@ -386,7 +388,7 @@ end
local function fieldappearances(specification)
-- todo: caching
- local values = specification.values
+ local values = specification.values
local default = specification.default -- todo
if not values then
-- error
@@ -402,22 +404,51 @@ local function fieldappearances(specification)
n, r, d = v[1], v[2], v[3]
end
local appearance = pdfdictionary {
- N = registeredsymbol(n), R = registeredsymbol(r), D = registeredsymbol(d),
+ N = registeredsymbol(n),
+ R = registeredsymbol(r),
+ D = registeredsymbol(d),
}
return pdfshareobjectreference(appearance)
-- return pdfreference(pdfflushobject(appearance))
end
-local YesorOn = "Yes" -- somehow On is not always working out well any longer (why o why this change)
-
--- beware ... maybe we should have unique /Yes1 ... we will probably
--- change this one too.
+-- The rendering part of form support has always been crappy and didn't really
+-- improve over time. Did bugs become features? Who knows. Why provide for instance
+-- control over appearance and then ignore it when the mouse clicks someplace else.
+-- Strangely enough a lot of effort went into JavaScript support while basic
+-- appearance control of checkboxes stayed poor. I found this link when googling for
+-- conformation after the n^th time looking into this behaviour:
+--
+-- https://stackoverflow.com/questions/15479855/pdf-appearance-streams-checkbox-not-shown-correctly-after-focus-lost
+--
+-- ... "In particular check boxes, therefore, whenever not interacting with the user, shall
+-- be displayed using their normal captions, not their appearances."
--
--- TODO: the same as radio .. play safe and use different names.
+-- So: don't use check boxes. In fact, even radio buttons can have these funny "flash some
+-- funny symbol" side effect when clocking on them. I tried all combinations if /H and /AP
+-- and /AS and ... Because (afaiks) the acrobat interface assumes that one uses dingbats no
+-- one really cared about getting custom appeances done well. This erratic behaviour might
+-- as well be the reason why no open source viewer ever bothered implementing forms. It's
+-- probably also why most forms out there look kind of bad.
+
+local function fieldstates_precheck(specification)
+ local values = specification.values
+ local default = specification.default
+ if not values or values == "" then
+ return
+ end
+ local yes = settings_to_array(values)[1]
+ local yesshown, yesvalue = lpegmatch(splitter,yes)
+ if not (yesshown and yesvalue) then
+ yesshown = yes
+ end
+ return default == settings_to_array(yesshown)[1] and pdf_yes or pdf_off
+end
-local function fieldstates_check(specification,forceyes,values,default,yesdefault)
+local function fieldstates_check(specification)
-- we don't use Opt here (too messy for radio buttons)
- local values, default = values or specification.values, default or specification.default
+ local values = specification.values
+ local default = specification.default
if not values or values == "" then
-- error
return
@@ -459,28 +490,27 @@ local function fieldstates_check(specification,forceyes,values,default,yesdefaul
if not offvalue then
offvalue = offn
end
- if forceyes == true then
- forceyes = YesorOn -- spec likes Yes more but we've used On for ages now
- else
- -- false or string
- end
if default == yesn then
- default = pdfconstant(forceyes or yesn)
+ default = pdf_yes
+ yesvalue = yesvalue == yesn and "Yes" or "Off"
else
- default = pdf_off
+ default = pdf_off
+ yesvalue = "Off"
end
local appearance
- if false then -- needs testing
+ -- if false then
+ if true then
+ -- needs testing
appearance = pdfdictionary { -- maybe also cache components
- N = pdfshareobjectreference(pdfdictionary { [forceyes or yesn] = registeredsymbol(yesn), Off = registeredsymbol(offn) }),
- R = pdfshareobjectreference(pdfdictionary { [forceyes or yesr] = registeredsymbol(yesr), Off = registeredsymbol(offr) }),
- D = pdfshareobjectreference(pdfdictionary { [forceyes or yesd] = registeredsymbol(yesd), Off = registeredsymbol(offd) }),
+ N = pdfshareobjectreference(pdfdictionary { Yes = registeredsymbol(yesn), Off = registeredsymbol(offn) }),
+ R = pdfshareobjectreference(pdfdictionary { Yes = registeredsymbol(yesr), Off = registeredsymbol(offr) }),
+ D = pdfshareobjectreference(pdfdictionary { Yes = registeredsymbol(yesd), Off = registeredsymbol(offd) }),
}
else
appearance = pdfdictionary { -- maybe also cache components
- N = pdfdictionary { [forceyes or yesn] = registeredsymbol(yesn), Off = registeredsymbol(offn) },
- R = pdfdictionary { [forceyes or yesr] = registeredsymbol(yesr), Off = registeredsymbol(offr) },
- D = pdfdictionary { [forceyes or yesd] = registeredsymbol(yesd), Off = registeredsymbol(offd) }
+ N = pdfdictionary { Yes = registeredsymbol(yesn), Off = registeredsymbol(offn) },
+ R = pdfdictionary { Yes = registeredsymbol(yesr), Off = registeredsymbol(offr) },
+ D = pdfdictionary { Yes = registeredsymbol(yesd), Off = registeredsymbol(offd) }
}
end
local appearanceref = pdfshareobjectreference(appearance)
@@ -488,12 +518,11 @@ local function fieldstates_check(specification,forceyes,values,default,yesdefaul
return appearanceref, default, yesvalue
end
--- It looks like there is always a (MK related) symbol used and that
--- the appearances are only used as ornaments behind a symbol. So,
--- contrary to what we did when widgets showed up, we now limit
--- ourself to more dumb definitions. Especially when highlighting is
--- enabled weird interferences happen. So, we play safe (some nice code
--- has been removed that worked well till recently).
+-- It looks like there is always a (MK related) symbol used and that the appearances
+-- are only used as ornaments behind a symbol. So, contrary to what we did when
+-- widgets showed up, we now limit ourself to more dumb definitions. Especially when
+-- highlighting is enabled weird interferences happen. So, we play safe (some nice
+-- code has been removed that worked well till recently).
local function fieldstates_radio(specification,name,parent)
local values = values or specification.values
@@ -572,7 +601,7 @@ local function fieldstates_radio(specification,name,parent)
return appearanceref, default, yesvalue
end
-local function fielddefault(field)
+local function fielddefault(field,pdf_yes)
local default = field.default
if not default or default == "" then
local values = settings_to_array(field.values)
@@ -581,12 +610,12 @@ local function fielddefault(field)
if not default or default == "" then
return pdf_off
else
- return pdfconstant(default)
+ return pdf_yes or pdfconstant(default)
end
end
local function fieldoptions(specification)
- local values = specification.values
+ local values = specification.values
local default = specification.default
if values then
local v = settings_to_array(values)
@@ -790,7 +819,9 @@ function codeinjections.definefield(specification)
end
function codeinjections.clonefield(specification) -- obsolete
- local p, c, v = specification.parent, specification.children, specification.alternative
+ local p = specification.parent
+ local c = specification.children
+ local v = specification.alternative
if not p or not c then
if trace_fields then
report_fields("invalid clone, children %a, parent %a, alternative %a",c,p,v)
@@ -874,7 +905,8 @@ local function enhance(specification,option)
return specification
end
--- finish
+-- finish (if we also collect parents we can inline the kids which is
+-- more efficient ... but hardly anyone used widgets so ...)
local collected = pdfarray()
local forceencoding = false
@@ -949,14 +981,14 @@ end
local function save_parent(field,specification,d,hasopt)
local kidsnum = pdfreserveobject()
- d.Kids = pdfreference(kidsnum)
+ d.Kids = pdfreference(kidsnum)
field.kidsnum = kidsnum
- field.kids = pdfarray()
+ field.kids = pdfarray()
if hasopt then
local optnum = pdfreserveobject()
- d.Opt = pdfreference(optnum)
+ d.Opt = pdfreference(optnum)
field.optnum = optnum
- field.opt = pdfarray()
+ field.opt = pdfarray()
end
local pnum = pdfflushobject(d)
field.pobj = pnum
@@ -972,16 +1004,21 @@ local function save_kid(field,specification,d,optname)
opt[#opt+1] = optname
end
end
- local width, height, depth = specification.width or 0, specification.height or 0, specification.depth
+ local width = specification.width or 0
+ local height = specification.height or 0
+ local depth = specification.depth or 0
local box = hpack_node(nodeinjections.annotation(width,height,depth,d(),kn))
- box.width, box.height, box.depth = width, height, depth -- redundant
+ -- redundant
+ box.width = width
+ box.height = height
+ box.depth = depth
return box
end
local function makelineparent(field,specification)
- local text = pdfunicode(field.default)
+ local text = pdfunicode(field.default)
local length = tonumber(specification.length or 0) or 0
- local d = pdfdictionary {
+ local d = pdfdictionary {
Subtype = pdf_widget,
T = pdfunicode(specification.title),
F = fieldplus(specification),
@@ -999,7 +1036,8 @@ local function makelineparent(field,specification)
end
local function makelinechild(name,specification)
- local field, parent = clones[name], nil
+ local field = clones[name]
+ local parent = nil
if field then
parent = fields[field.parent]
if not parent.pobj then
@@ -1010,7 +1048,7 @@ local function makelinechild(name,specification)
end
else
parent = fields[name]
- field = parent
+ field = parent
if not parent.pobj then
if trace_fields then
report_fields("using parent text %a",name)
@@ -1047,9 +1085,9 @@ end
-- copy of line ... probably also needs a /Lock
local function makesignatureparent(field,specification)
- local text = pdfunicode(field.default)
+ local text = pdfunicode(field.default)
local length = tonumber(specification.length or 0) or 0
- local d = pdfdictionary {
+ local d = pdfdictionary {
Subtype = pdf_widget,
T = pdfunicode(specification.title),
F = fieldplus(specification),
@@ -1067,7 +1105,8 @@ local function makesignatureparent(field,specification)
end
local function makesignaturechild(name,specification)
- local field, parent = clones[name], nil
+ local field = clones[name]
+ local parent = nil
if field then
parent = fields[field.parent]
if not parent.pobj then
@@ -1078,7 +1117,7 @@ local function makesignaturechild(name,specification)
end
else
parent = fields[name]
- field = parent
+ field = parent
if not parent.pobj then
if trace_fields then
report_fields("using parent text %a",name)
@@ -1124,7 +1163,8 @@ local function makechoiceparent(field,specification)
end
local function makechoicechild(name,specification)
- local field, parent = clones[name], nil
+ local field = clones[name]
+ local parent = nil
if field then
parent = fields[field.parent]
if not parent.pobj then
@@ -1135,7 +1175,7 @@ local function makechoicechild(name,specification)
end
else
parent = fields[name]
- field = parent
+ field = parent
if not parent.pobj then
if trace_fields then
report_fields("using parent choice %a",name)
@@ -1169,20 +1209,22 @@ function methods.combo(name,specification)
end
local function makecheckparent(field,specification)
+ local default = fieldstates_precheck(field)
local d = pdfdictionary {
T = pdfunicode(specification.title), -- todo: when tracing use a string
F = fieldplus(specification),
Ff = fieldflag(specification),
OC = fieldlayer(specification),
- AA = fieldactions(specification),
+ AA = fieldactions(specification), -- can be shared
FT = pdf_btn,
- V = fielddefault(field),
+ V = fielddefault(field,default),
}
save_parent(field,specification,d,true)
end
local function makecheckchild(name,specification)
- local field, parent = clones[name], nil
+ local field = clones[name]
+ local parent = nil
if field then
parent = fields[field.parent]
if not parent.pobj then
@@ -1193,7 +1235,7 @@ local function makecheckchild(name,specification)
end
else
parent = fields[name]
- field = parent
+ field = parent
if not parent.pobj then
if trace_fields then
report_fields("using parent check %a",name)
@@ -1209,7 +1251,7 @@ local function makecheckchild(name,specification)
Parent = pdfreference(parent.pobj),
F = fieldplus(specification),
OC = fieldlayer(specification),
- AA = fieldactions(specification),
+ AA = fieldactions(specification), -- can be shared
H = pdf_n,
}
local fontsymbol = specification.fontsymbol
@@ -1221,10 +1263,10 @@ local function makecheckchild(name,specification)
d.MK = fieldrendering(specification)
return save_kid(parent,specification,d)
else
- local appearance, default, value = fieldstates_check(field,true)
+ local appearance, default, value = fieldstates_check(field)
d.AS = default
d.AP = appearance
- return save_kid(parent,specification,d,value)
+ return save_kid(parent,specification,d)
end
end
@@ -1239,7 +1281,7 @@ local function makepushparent(field,specification) -- check if we can share with
F = fieldplus(specification),
Ff = fieldflag(specification),
OC = fieldlayer(specification),
- AA = fieldactions(specification),
+ AA = fieldactions(specification), -- can be shared
FT = pdf_btn,
AP = fieldappearances(field),
H = pdf_p,
@@ -1276,7 +1318,7 @@ local function makepushchild(name,specification)
Parent = pdfreference(field.pobj),
F = fieldplus(specification),
OC = fieldlayer(specification),
- AA = fieldactions(specification),
+ AA = fieldactions(specification), -- can be shared
H = pdf_p,
}
if fontsymbol and fontsymbol ~= "" then
@@ -1311,7 +1353,7 @@ end
local function makeradiochild(name,specification)
local field, parent = clones[name], nil
if field then
- field = radios[field.parent]
+ field = radios[field.parent]
parent = fields[field.parent]
if not parent.pobj then
if trace_fields then
diff --git a/tex/context/base/mkiv/lpdf-fmt.lua b/tex/context/base/mkiv/lpdf-fmt.lua
index 0830d2d8d..25a72fa49 100644
--- a/tex/context/base/mkiv/lpdf-fmt.lua
+++ b/tex/context/base/mkiv/lpdf-fmt.lua
@@ -116,6 +116,7 @@ local formats = utilities.storage.allocate {
jbig2_compression = true, -- todo: block at lua level
jpeg2000_compression = true, -- todo: block at lua level
include_cidsets = true,
+ include_charsets = true,
inject_metadata = function()
-- nothing
end
@@ -131,6 +132,7 @@ local formats = utilities.storage.allocate {
spot_colors = true,
internal_icc_profiles = true,
include_cidsets = true,
+ include_charsets = true,
inject_metadata = function()
addtoinfo("GTS_PDFXVersion","PDF/X-1a:2001")
injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfxid='http://www.npes.org/pdfx/ns/id/'><pdfxid:GTS_PDFXVersion>PDF/X-1a:2001</pdfxid:GTS_PDFXVersion></rdf:Description>",false)
@@ -146,6 +148,7 @@ local formats = utilities.storage.allocate {
spot_colors = true,
internal_icc_profiles = true,
include_cidsets = true,
+ include_charsets = true,
inject_metadata = function()
addtoinfo("GTS_PDFXVersion","PDF/X-1a:2003")
injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfxid='http://www.npes.org/pdfx/ns/id/'><pdfxid:GTS_PDFXVersion>PDF/X-1a:2003</pdfxid:GTS_PDFXVersion></rdf:Description>",false)
@@ -165,6 +168,7 @@ local formats = utilities.storage.allocate {
internal_icc_profiles = true,
include_intents = true,
include_cidsets = true,
+ include_charsets = true,
inject_metadata = function()
addtoinfo("GTS_PDFXVersion","PDF/X-3:2002")
end
@@ -184,6 +188,7 @@ local formats = utilities.storage.allocate {
include_intents = true,
jbig2_compression = true,
include_cidsets = true,
+ include_charsets = true,
inject_metadata = function()
addtoinfo("GTS_PDFXVersion","PDF/X-3:2003")
end
@@ -207,6 +212,7 @@ local formats = utilities.storage.allocate {
jpeg2000_compression = true,
object_compression = true,
include_cidsets = true,
+ include_charsets = true,
inject_metadata = function()
injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfxid='http://www.npes.org/pdfx/ns/id/'><pdfxid:GTS_PDFXVersion>PDF/X-4</pdfxid:GTS_PDFXVersion></rdf:Description>",false)
insertxmpinfo("xml://rdf:Description/xmpMM:InstanceID","<xmpMM:VersionID>1</xmpMM:VersionID>",false)
@@ -233,6 +239,7 @@ local formats = utilities.storage.allocate {
jpeg2000_compression = true,
object_compression = true,
include_cidsets = true,
+ include_charsets = true,
inject_metadata = function()
injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfxid='http://www.npes.org/pdfx/ns/id/'><pdfxid:GTS_PDFXVersion>PDF/X-4p</pdfxid:GTS_PDFXVersion></rdf:Description>",false)
insertxmpinfo("xml://rdf:Description/xmpMM:InstanceID","<xmpMM:VersionID>1</xmpMM:VersionID>",false)
@@ -259,6 +266,7 @@ local formats = utilities.storage.allocate {
jpeg2000_compression = true,
object_compression = true,
include_cidsets = true,
+ include_charsets = true,
inject_metadata = function()
-- todo
end
@@ -284,6 +292,7 @@ local formats = utilities.storage.allocate {
jpeg2000_compression = true,
object_compression = true,
include_cidsets = true,
+ include_charsets = true,
inject_metadata = function()
-- todo
end
@@ -308,6 +317,7 @@ local formats = utilities.storage.allocate {
nchannel_colorspace = true,
object_compression = true,
include_cidsets = true,
+ include_charsets = true,
inject_metadata = function()
-- todo
end
@@ -328,6 +338,7 @@ local formats = utilities.storage.allocate {
tagging = true, -- NEW; the only difference to PDF/A-1b
internal_icc_profiles = true,
include_cidsets = true,
+ include_charsets = true,
inject_metadata = function()
injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfaid='http://www.aiim.org/pdfa/ns/id/'><pdfaid:part>1</pdfaid:part><pdfaid:conformance>A</pdfaid:conformance></rdf:Description>",false)
end
@@ -347,6 +358,7 @@ local formats = utilities.storage.allocate {
forms = true,
internal_icc_profiles = true,
include_cidsets = true,
+ include_charsets = true,
inject_metadata = function()
injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfaid='http://www.aiim.org/pdfa/ns/id/'><pdfaid:part>1</pdfaid:part><pdfaid:conformance>B</pdfaid:conformance></rdf:Description>",false)
end
@@ -371,6 +383,7 @@ local formats = utilities.storage.allocate {
jpeg2000_compression = true, -- NEW
object_compression = true,
include_cidsets = false,
+ include_charsets = false,
inject_metadata = function()
injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfaid='http://www.aiim.org/pdfa/ns/id/'><pdfaid:part>2</pdfaid:part><pdfaid:conformance>A</pdfaid:conformance></rdf:Description>",false)
end
@@ -395,6 +408,7 @@ local formats = utilities.storage.allocate {
jpeg2000_compression = true,
object_compression = true,
include_cidsets = false,
+ include_charsets = false,
inject_metadata = function()
injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfaid='http://www.aiim.org/pdfa/ns/id/'><pdfaid:part>3</pdfaid:part><pdfaid:conformance>A</pdfaid:conformance></rdf:Description>",false)
end
@@ -418,6 +432,7 @@ local formats = utilities.storage.allocate {
jpeg2000_compression = true,
object_compression = true,
include_cidsets = true,
+ include_charsets = true, --- really ?
inject_metadata = function()
injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfaid='http://www.aiim.org/pdfa/ns/id/'><pdfaid:part>3</pdfaid:part><pdfaid:conformance>A</pdfaid:conformance></rdf:Description>",false)
injectxmpinfo("xml://rdf:RDF","<rdf:Description rdf:about='' xmlns:pdfuaid='http://www.aiim.org/pdfua/ns/id/'><pdfuaid:part>1</pdfuaid:part></rdf:Description>",false)
@@ -753,7 +768,11 @@ function codeinjections.setformat(s)
majorversion,minorversion)
end
--
- pdf.setomitcidset(formatspecification.include_cidsets == false and 1 or 0)
+ -- cid sets can always omitted now, but those validators still complain so let's
+ -- for a while keep it (for luigi):
+ --
+ lpdf.setomitcidset (formatspecification.include_cidsets == false and 1 or 0)
+ lpdf.setomitcharset(formatspecification.include_charsets == false and 1 or 0)
--
-- context.setupcolors { -- not this way
-- cmyk = spec.cmyk_colors and variables.yes or variables.no,
diff --git a/tex/context/base/mkiv/lpdf-fnt.lua b/tex/context/base/mkiv/lpdf-fnt.lua
new file mode 100644
index 000000000..1caa2f93c
--- /dev/null
+++ b/tex/context/base/mkiv/lpdf-fnt.lua
@@ -0,0 +1,202 @@
+if not modules then modules = { } end modules ['lpdf-fnt'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is experimental code.
+
+local match, gmatch = string.match, string.gmatch
+local tonumber = tonumber
+
+local pdfreserveobject = lpdf.reserveobject
+local pdfincludechar = lpdf.includechar
+local pdfincludefont = lpdf.includefont
+local pdfreference = lpdf.reference
+
+local pdfe = lpdf.epdf
+
+local tobemerged = { }
+local trace_merge = false trackers.register("graphics.fonts",function(v) trace_merge = v end)
+local report_merge = logs.reporter("graphics","fonts")
+
+local function register(usedname,cleanname)
+ local cleanname = cleanname or fonts.names.cleanname(usedname)
+ local fontid = fonts.definers.internal { name = cleanname }
+ if fontid then
+ local objref = pdfreserveobject()
+ pdfincludefont(fontid)
+ if trace_merge then
+ report_merge("registering %a with name %a, id %a and object %a",usedname,cleanname,fontid,objref)
+ end
+ return {
+ id = fontid,
+ reference = objref,
+ indices = { },
+ cleanname = cleanname,
+ }
+ end
+ return false
+end
+
+function lpdf.registerfont(usedname,cleanname)
+ local v = register(usedname,cleanname)
+ tobemerged[usedname] = v
+ return v
+end
+
+table.setmetatableindex(tobemerged,function(t,k)
+ return lpdf.registerfont(k)
+end)
+
+local function finalizefont(v)
+ local indextoslot = fonts.helpers.indextoslot
+ if v then
+ local id = v.id
+ local n = 0
+ for i in next, v.indices do
+ local u = indextoslot(id,i)
+ -- pdfincludechar(id,u)
+ n = n + 1
+ end
+ v.n = n
+ end
+end
+
+statistics.register("merged fonts", function()
+ if next(tobemerged) then
+ local t = { }
+ for k, v in table.sortedhash(tobemerged) do
+ t[#t+1] = string.formatters["%s (+%i)"](k,v.n)
+ end
+ return table.concat(t," ")
+ end
+end)
+
+function lpdf.finalizefonts()
+ for k, v in next, tobemerged do
+ finalizefont(v)
+ end
+end
+
+callback.register("font_descriptor_objnum_provider",function(name)
+ local m = rawget(tobemerged,name)
+ if m then
+ -- finalizefont(m)
+ local r = m.reference or 0
+ if trace_merge then
+ report_merge("using object %a for font descriptor of %a",r,name)
+ end
+ return r
+ end
+ return 0
+end)
+
+local function getunicodes1(str,indices)
+ for s in gmatch(str,"beginbfrange%s*(.-)%s*endbfrange") do
+ for first, last, offset in gmatch(s,"<([^>]+)>%s+<([^>]+)>%s+<([^>]+)>") do
+ for i=tonumber(first,16),tonumber(last,16) do
+ indices[i] = true
+ end
+ end
+ end
+ for s in gmatch(str,"beginbfchar%s*(.-)%s*endbfchar") do
+ for old, new in gmatch(s,"<([^>]+)>%s+<([^>]+)>") do
+ indices[tonumber(old,16)] = true
+ end
+ end
+end
+
+local function getunicodes2(widths,indices)
+ for i=1,#widths,2 do
+ local start = widths[i]
+ local count = #widths[i+1]
+ if start and count then
+ for i=start,start+count-1 do
+ indices[i] = true
+ end
+ end
+ end
+end
+
+local function checkedfonts(pdfdoc,xref,copied,page)
+ local list = page.Resources.Font
+ local done = { }
+ for k, somefont in pdfe.expanded(list) do
+ if somefont.Subtype == "Type0" and somefont.Encoding == "Identity-H" then
+ local descendants = somefont.DescendantFonts
+ if descendants then
+ for i=1,#descendants do
+ local d = descendants[i]
+ if d then
+ local subtype = d.Subtype
+ if subtype == "CIDFontType0" or subtype == "CIDFontType2" then
+ local basefont = somefont.BaseFont
+ if basefont then
+ local fontname = match(basefont,"^[A-Z]+%+(.+)$")
+ local fontdata = tobemerged[fontname]
+ if fontdata then
+ local descriptor = d.FontDescriptor
+ if descriptor then
+ local okay = false
+ local widths = d.W
+ if widths then
+ getunicodes2(widths,fontdata.indices)
+ okay = true
+ else
+ local tounicode = somefont.ToUnicode
+ if tounicode then
+ getunicodes1(tounicode(),fontdata.indices)
+ okay = true
+ end
+ end
+ if okay then
+ local r = xref[descriptor]
+ done[r] = fontdata.reference
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ return next(done) and done
+end
+
+if pdfincludefont then
+
+ function lpdf.epdf.plugin(pdfdoc,xref,copied,page)
+ local done = checkedfonts(pdfdoc,xref,copied,page)
+ if done then
+ return {
+ FontDescriptor = function(xref,copied,object,key,value,copyobject)
+ local r = value[3]
+ local d = done[r]
+ if d then
+ return pdfreference(d)
+ else
+ return copyobject(xref,copied,object,key,value)
+ end
+ end
+ }
+ end
+ end
+
+else
+
+ function lpdf.epdf.plugin() end
+
+end
+
+lpdf.registerdocumentfinalizer(lpdf.finalizefonts)
+
+-- already defined in font-ocl but the context variatn will go here
+--
+-- function lpdf.vfimage(wd,ht,dp,data,name)
+-- return { "image", { filename = name, width = wd, height = ht, depth = dp } }
+-- end
diff --git a/tex/context/base/mkiv/lpdf-grp.lua b/tex/context/base/mkiv/lpdf-grp.lua
index 34925fddd..49cc76871 100644
--- a/tex/context/base/mkiv/lpdf-grp.lua
+++ b/tex/context/base/mkiv/lpdf-grp.lua
@@ -29,6 +29,10 @@ local pdfboolean = lpdf.boolean
local pdfreference = lpdf.reference
local pdfflushobject = lpdf.flushobject
+local createimage = images.create
+local wrapimage = images.wrap
+local embedimage = images.embed
+
-- can also be done indirectly:
--
-- 12 : << /AntiAlias false /ColorSpace 8 0 R /Coords [ 0.0 0.0 1.0 0.0 ] /Domain [ 0.0 1.0 ] /Extend [ true true ] /Function 22 0 R /ShadingType 2 >>
@@ -153,13 +157,18 @@ function nodeinjections.injectbitmap(t)
elseif height == 0 then
height = width * yresolution / xresolution
end
- local image = img.new {
+ local a = pdfdictionary {
+ BBox = pdfarray { 0, 0, urx * basepoints, ury * basepoints }
+ }
+ local image = createimage {
stream = formatters[template](d(),t.data),
width = width,
height = height,
bbox = { 0, 0, urx, ury },
+ attr = a(),
+ nobbox = true,
}
- return img.node(image)
+ return wrapimage(image)
end
-- general graphic helpers
@@ -181,7 +190,7 @@ function codeinjections.setfigurealternative(data,figure)
local displayfigure = figures.check()
if displayfigure then
-- figure.aform = true
- img.immediatewrite(figure)
+ embedimage(figure)
local a = pdfarray {
pdfdictionary {
Image = pdfreference(figure.objnum),
@@ -215,14 +224,14 @@ function codeinjections.getpreviewfigure(request)
end
local image = figure.status.private
if image then
- img.immediatewrite(image)
+ embedimage(image)
end
return figure
end
function codeinjections.setfiguremask(data,figure) -- mark
local request = data.request
- local mask = request.mask
+ local mask = request.mask
if mask and mask ~= "" then
figures.push {
name = mask,
@@ -233,15 +242,16 @@ function codeinjections.setfiguremask(data,figure) -- mark
width = request.width,
height = request.height,
}
- figures.identify()
- local maskfigure = figures.check()
- if maskfigure then
- local image = maskfigure.status.private
+ mask = figures.identify()
+ mask = figures.check(mask)
+ if mask then
+ local image = mask.status.private
if image then
- img.immediatewrite(image)
+ figures.include(mask)
+ embedimage(image)
local d = pdfdictionary {
Interpolate = false,
- SMask = pdfreference(image.objnum),
+ SMask = pdfreference(mask.status.objectnumber),
}
figure.attr = d()
end
@@ -250,39 +260,16 @@ function codeinjections.setfiguremask(data,figure) -- mark
end
end
--- temp hack
+-- experimental (q Q is not really needed)
-function img.package(image) -- see lpdf-u3d **
- local boundingbox = image.bbox
- local imagetag = "Im" .. image.index
- local resources = pdfdictionary {
- ProcSet = pdfarray {
- pdfconstant("PDF"),
- pdfconstant("ImageC")
- },
- Resources = pdfdictionary {
- XObject = pdfdictionary {
- [imagetag] = pdfreference(image.objnum)
- }
- }
- }
- local width = boundingbox[3]
- local height = boundingbox[4]
- local xform = img.scan {
- attr = resources(),
- stream = formatters["%.6F 0 0 %.6F 0 0 cm /%s Do"](width,height,imagetag),
- bbox = { 0, 0, width/basepoints, height/basepoints },
- }
- img.immediatewrite(xform)
- return xform
-end
+local f_pattern = formatters["q /Pattern cs /%s scn 0 0 %.6F %.6F re f Q"]
--- experimental
+directives.register("pdf.stripzeros",function()
+ f_pattern = formatters["q /Pattern cs /%s scn 0 0 %.6N %.6N re f Q"]
+end)
-local nofpatterns = 0
-local f_pattern = formatters["q /Pattern cs /%s scn 0 0 %.6F %.6F re f Q"] -- q Q is not really needed
-
-local texsavebox = tex.saveboxresource
+local saveboxresource = tex.boxresources.save
+local nofpatterns = 0
function lpdf.registerpattern(specification)
nofpatterns = nofpatterns + 1
@@ -299,10 +286,11 @@ function lpdf.registerpattern(specification)
(specification.voffset or 0) * basepoints,
},
}
+
local resources = lpdf.collectedresources{ patterns = false }
local attributes = d()
local onlybounds = 1
- local patternobj = texsavebox(specification.number,attributes,resources,true,onlybounds)
+ local patternobj = saveboxresource(specification.number,attributes,resources,true,onlybounds)
lpdf.adddocumentpattern("Pt" .. nofpatterns,lpdf.reference(patternobj ))
return nofpatterns
end
diff --git a/tex/context/base/mkiv/lpdf-ini.lua b/tex/context/base/mkiv/lpdf-ini.lua
index 8af1fb409..ec837449f 100644
--- a/tex/context/base/mkiv/lpdf-ini.lua
+++ b/tex/context/base/mkiv/lpdf-ini.lua
@@ -13,7 +13,8 @@ local char, byte, format, gsub, concat, match, sub, gmatch = string.char, string
local utfchar, utfbyte, utfvalues = utf.char, utf.byte, utf.values
local sind, cosd, max, min = math.sind, math.cosd, math.max, math.min
local sort = table.sort
-local lpegmatch, P, C, R, S, Cc, Cs = lpeg.match, lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs
+local P, C, R, S, Cc, Cs, V = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs, lpeg.V
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local formatters = string.formatters
local isboolean = string.is_boolean
local rshift = bit32.rshift
@@ -31,217 +32,234 @@ local context = context
-- encoded utf16 string type between <>. We could probably save some bytes by using
-- strings between () but then we end up with escaped ()\ too.
--- gethpos : used
--- getpos : used
--- getvpos : used
---
--- getmatrix : used
--- hasmatrix : used
---
--- mapfile : used in font-ctx.lua
--- mapline : used in font-ctx.lua
---
--- maxobjnum : not used
--- obj : used
--- immediateobj : used
--- objtype : not used
--- pageref : used
--- print : can be used
--- refobj : used
--- registerannot : not to be used
--- reserveobj : used
-
--- pdf.catalog : used
--- pdf.info : used
--- pdf.trailer : used
--- pdf.names : not to be used
-
--- pdf.setinfo : used
--- pdf.setcatalog : used
--- pdf.setnames : not to be used
--- pdf.settrailer : used
-
--- pdf.getinfo : used
--- pdf.getcatalog : used
--- pdf.getnames : not to be used
--- pdf.gettrailer : used
-
-local pdf = pdf
-local factor = number.dimenfactors.bp
-
-local pdfsetinfo = pdf.setinfo
-local pdfsetcatalog = pdf.setcatalog
------ pdfsettrailerid = pdf.settrailerid
------ pdfsetnames = pdf.setnames
------ pdfsettrailer = pdf.settrailer
-
-local pdfsetpageresources = pdf.setpageresources
-local pdfsetpageattributes = pdf.setpageattributes
-local pdfsetpagesattributes = pdf.setpagesattributes
-
-local pdfgetpos = pdf.getpos
-local pdfgethpos = pdf.gethpos
-local pdfgetvpos = pdf.getvpos
-local pdfgetmatrix = pdf.getmatrix
-local pdfhasmatrix = pdf.hasmatrix
-
-local pdfreserveobject = pdf.reserveobj
-local pdfimmediateobject = pdf.immediateobj
-local pdfdeferredobject = pdf.obj
-local pdfreferenceobject = pdf.refobj
-
-local function pdfdisablecommand(command)
- pdf[command] = function() report_blocked("'pdf.%s' is not supported",command) end
-end
+pdf = type(pdf) == "table" and pdf or { }
+local factor = number.dimenfactors.bp
-pdfdisablecommand("setinfo")
-pdfdisablecommand("setcatalog")
-pdfdisablecommand("setnames")
-pdfdisablecommand("settrailer")
-pdfdisablecommand("setpageresources")
-pdfdisablecommand("setpageattributes")
-pdfdisablecommand("setpagesattributes")
-pdfdisablecommand("registerannot")
+local codeinjections = { }
+local nodeinjections = { }
-pdf.disablecommand = pdfdisablecommand
+local backends = backends
-local trace_finalizers = false trackers.register("backend.finalizers", function(v) trace_finalizers = v end)
-local trace_resources = false trackers.register("backend.resources", function(v) trace_resources = v end)
-local trace_objects = false trackers.register("backend.objects", function(v) trace_objects = v end)
-local trace_detail = false trackers.register("backend.detail", function(v) trace_detail = v end)
-
-local backends = backends
-local pdfbackend = {
+local pdfbackend = {
comment = "backend for directly generating pdf output",
- nodeinjections = { },
- codeinjections = { },
+ nodeinjections = nodeinjections,
+ codeinjections = codeinjections,
registrations = { },
tables = { },
}
-backends.pdf = pdfbackend
-lpdf = lpdf or { }
-local lpdf = lpdf
-lpdf.flags = lpdf.flags or { } -- will be filled later
+backends.pdf = pdfbackend
-do
+lpdf = lpdf or { }
+local lpdf = lpdf
+lpdf.flags = lpdf.flags or { } -- will be filled later
+
+local trace_finalizers = false trackers.register("backend.finalizers", function(v) trace_finalizers = v end)
+local trace_resources = false trackers.register("backend.resources", function(v) trace_resources = v end)
+local trace_objects = false trackers.register("backend.objects", function(v) trace_objects = v end)
+local trace_detail = false trackers.register("backend.detail", function(v) trace_detail = v end)
- local setmajorversion = pdf.setmajorversion
- local setminorversion = pdf.setminorversion
- local getmajorversion = pdf.getmajorversion
- local getminorversion = pdf.getminorversion
+do
- if not setmajorversion then
+ local pdfsetmajorversion, pdfsetminorversion, pdfgetmajorversion, pdfgetminorversion
+ local pdfsetcompresslevel, pdfsetobjectcompresslevel, pdfgetcompresslevel, pdfgetobjectcompresslevel
+ local pdfsetsuppressoptionalinfo, pdfsetomitcidset, pdfsetomitcharset
- setmajorversion = function() end
- getmajorversion = function() return 1 end
+ updaters.register("backend.update.lpdf",function()
+ pdfsetmajorversion = pdf.setmajorversion
+ pdfsetminorversion = pdf.setminorversion
+ pdfgetmajorversion = pdf.getmajorversion
+ pdfgetminorversion = pdf.getminorversion
- pdf.setmajorversion = setmajorversion
- pdf.getmajorversion = getmajorversion
+ pdfsetcompresslevel = pdf.setcompresslevel
+ pdfsetobjectcompresslevel = pdf.setobjcompresslevel
+ pdfgetcompresslevel = pdf.getcompresslevel
+ pdfgetobjectcompresslevel = pdf.getobjcompresslevel
- end
+ pdfsetsuppressoptionalinfo = pdf.setsuppressoptionalinfo
+ pdfsetomitcidset = pdf.setomitcidset
+ pdfsetomitcharset = pdf.setomitcharset
+ end)
function lpdf.setversion(major,minor)
- setmajorversion(major or 1)
- setminorversion(minor or 7)
+ pdfsetmajorversion(major or 1)
+ pdfsetminorversion(minor or 7)
end
function lpdf.getversion(major,minor)
- return getmajorversion(), getminorversion()
+ return pdfgetmajorversion(), pdfgetminorversion()
end
- lpdf.majorversion = getmajorversion
- lpdf.minorversion = getminorversion
-
-end
-
-do
-
- local setcompresslevel = pdf.setcompresslevel
- local setobjectcompresslevel = pdf.setobjcompresslevel
- local getcompresslevel = pdf.getcompresslevel
- local getobjectcompresslevel = pdf.getobjcompresslevel
+ function lpdf.majorversion() return pdfgetmajorversion() end
+ function lpdf.minorversion() return pdfgetminorversion() end
local frozen = false
+ local clevel = 3
+ local olevel = 1
function lpdf.setcompression(level,objectlevel,freeze)
if not frozen then
- setcompresslevel(level or 3)
- setobjectcompresslevel(objectlevel or level or 3)
+ if pdfsetcompresslevel then
+ pdfsetcompresslevel(level or 3)
+ pdfsetobjectcompresslevel(objectlevel or level or 3)
+ else
+ clevel = level
+ olevel = objectlevel
+ end
frozen = freeze
end
end
function lpdf.getcompression()
- return getcompresslevel(), getobjectcompresslevel()
+ if pdfgetcompresslevel then
+ return pdfgetcompresslevel(), pdfgetobjectcompresslevel()
+ else
+ return clevel, olevel
+ end
end
- lpdf.compresslevel = getcompresslevel
- lpdf.objectcompresslevel = getobjectcompresslevel
+ function lpdf.compresslevel()
+ if pdfgetcompresslevel then
+ return pdfgetcompresslevel()
+ else
+ return clevel
+ end
+ end
-end
+ function lpdf.objectcompresslevel()
+ if pdfgetobjectcompresslevel then
+ return pdfgetobjectcompresslevel()
+ else
+ return olevel
+ end
+ end
-local codeinjections = pdfbackend.codeinjections
-local nodeinjections = pdfbackend.nodeinjections
-
-codeinjections.getpos = pdfgetpos lpdf.getpos = pdfgetpos
-codeinjections.gethpos = pdfgethpos lpdf.gethpos = pdfgethpos
-codeinjections.getvpos = pdfgetvpos lpdf.getvpos = pdfgetvpos
-codeinjections.hasmatrix = pdfhasmatrix lpdf.hasmatrix = pdfhasmatrix
-codeinjections.getmatrix = pdfgetmatrix lpdf.getmatrix = pdfgetmatrix
-
--- local function transform(llx,lly,urx,ury,rx,sx,sy,ry)
--- local x1 = llx * rx + lly * sy
--- local y1 = llx * sx + lly * ry
--- local x2 = llx * rx + ury * sy
--- local y2 = llx * sx + ury * ry
--- local x3 = urx * rx + lly * sy
--- local y3 = urx * sx + lly * ry
--- local x4 = urx * rx + ury * sy
--- local y4 = urx * sx + ury * ry
--- llx = min(x1,x2,x3,x4);
--- lly = min(y1,y2,y3,y4);
--- urx = max(x1,x2,x3,x4);
--- ury = max(y1,y2,y3,y4);
--- return llx, lly, urx, ury
--- end
+ function lpdf.setsuppressoptionalinfo(n)
+ if pdfsetsuppressoptionalinfo then
+ pdfsetsuppressoptionalinfo(n) -- todo
+ end
+ end
-function lpdf.transform(llx,lly,urx,ury) -- not yet used so unchecked
- if pdfhasmatrix() then
- local sx, rx, ry, sy = pdfgetmatrix()
- local w, h = urx - llx, ury - lly
- return llx, lly, llx + sy*w - ry*h, lly + sx*h - rx*w
- -- return transform(llx,lly,urx,ury,sx,rx,ry,sy)
- else
- return llx, lly, urx, ury
+ function lpdf.setomitcidset(v)
+ return pdfsetomitcidset(v)
end
+
+ function lpdf.setomitcharset(v)
+ return pdfsetomitcharset(v)
+ end
+
end
--- funny values for tx and ty
-
-function lpdf.rectangle(width,height,depth,offset)
- local tx, ty = pdfgetpos()
- if offset then
- tx = tx - offset
- ty = ty + offset
- width = width + 2*offset
- height = height + offset
- depth = depth + offset
- end
- if pdfhasmatrix() then
- local rx, sx, sy, ry = pdfgetmatrix()
- return
- factor * tx,
- factor * (ty - ry*depth + sx*width),
- factor * (tx + rx*width - sy*height),
- factor * (ty + ry*height - sx*width)
- else
- return
- factor * tx,
- factor * (ty - depth),
- factor * (tx + width),
- factor * (ty + height)
+do
+
+ local pdfgetxformname, pdfincludeimage
+
+ updaters.register("backend.update.lpdf",function()
+ pdfgetxformname = pdf.getxformname
+ pdfincludeimage = pdf.includeimage
+ end)
+
+ function lpdf.getxformname(id) return pdfgetxformname(id) end
+ function lpdf.includeimage(id) return pdfincludeimage(id) end
+
+end
+
+ local pdfsetpageresources, pdfsetpageattributes, pdfsetpagesattributes
+ local pdfreserveobject, pdfimmediateobject, pdfdeferredobject, pdfreferenceobject
+ local pdfgetpagereference
+
+ updaters.register("backend.update.lpdf",function()
+ pdfreserveobject = pdf.reserveobj
+ pdfimmediateobject = pdf.immediateobj
+ pdfdeferredobject = pdf.obj
+ pdfreferenceobject = pdf.refobj
+
+ pdfgetpagereference = pdf.getpageref
+
+ pdfsetpageresources = pdf.setpageresources
+ pdfsetpageattributes = pdf.setpageattributes
+ pdfsetpagesattributes = pdf.setpagesattributes
+ end)
+
+local jobpositions = job.positions
+local getpos = jobpositions.getpos
+
+jobpositions.registerhandlers {
+ getpos = pdf.getpos,
+ gethpos = pdf.gethpos,
+ getvpos = pdf.getvpos,
+}
+
+do
+
+ local pdfgetmatrix, pdfhasmatrix, pdfprint
+
+ updaters.register("backend.update.lpdf",function()
+ pdfgetmatrix = pdf.getmatrix
+ pdfhasmatrix = pdf.hasmatrix
+ pdfprint = pdf.print
+ end)
+
+ function lpdf.print(...)
+ return pdfprint(...)
+ end
+
+ pdfbackend.codeinjections.print = lpdf.print -- will go
+
+ -- local function transform(llx,lly,urx,ury,rx,sx,sy,ry)
+ -- local x1 = llx * rx + lly * sy
+ -- local y1 = llx * sx + lly * ry
+ -- local x2 = llx * rx + ury * sy
+ -- local y2 = llx * sx + ury * ry
+ -- local x3 = urx * rx + lly * sy
+ -- local y3 = urx * sx + lly * ry
+ -- local x4 = urx * rx + ury * sy
+ -- local y4 = urx * sx + ury * ry
+ -- llx = min(x1,x2,x3,x4);
+ -- lly = min(y1,y2,y3,y4);
+ -- urx = max(x1,x2,x3,x4);
+ -- ury = max(y1,y2,y3,y4);
+ -- return llx, lly, urx, ury
+ -- end
+ --
+ -- function lpdf.transform(llx,lly,urx,ury) -- not yet used so unchecked
+ -- if pdfhasmatrix() then
+ -- local sx, rx, ry, sy = pdfgetmatrix()
+ -- local w, h = urx - llx, ury - lly
+ -- return llx, lly, llx + sy*w - ry*h, lly + sx*h - rx*w
+ -- -- return transform(llx,lly,urx,ury,sx,rx,ry,sy)
+ -- else
+ -- return llx, lly, urx, ury
+ -- end
+ -- end
+
+ -- funny values for tx and ty
+
+ function lpdf.rectangle(width,height,depth,offset)
+ local tx, ty = getpos()
+ if offset then
+ tx = tx - offset
+ ty = ty + offset
+ width = width + 2*offset
+ height = height + offset
+ depth = depth + offset
+ end
+ if pdfhasmatrix() then
+ local rx, sx, sy, ry = pdfgetmatrix()
+ return
+ factor * tx,
+ factor * (ty - ry*depth + sx*width),
+ factor * (tx + rx*width - sy*height),
+ factor * (ty + ry*height - sx*width)
+ else
+ return
+ factor * tx,
+ factor * (ty - depth),
+ factor * (tx + width),
+ factor * (ty + height)
+ end
end
+
end
-- we could use a hash of predefined unicodes
@@ -265,204 +283,290 @@ end
-- end
-- end
-local cache = table.setmetatableindex(function(t,k) -- can be made weak
- local v = utfbyte(k)
- if v < 0x10000 then
- v = format("%04x",v)
- else
- v = format("%04x%04x",rshift(v,10),v%1024+0xDC00)
+local tosixteen, fromsixteen, topdfdoc, frompdfdoc, toeight, fromeight
+
+do
+
+ local escaped = Cs(Cc("(") * (S("\\()\n\r\t\b\f")/"\\%0" + P(1))^0 * Cc(")"))
+
+ local cache = table.setmetatableindex(function(t,k) -- can be made weak
+ local v = utfbyte(k)
+ if v < 0x10000 then
+ v = format("%04x",v)
+ else
+ v = format("%04x%04x",rshift(v,10),v%1024+0xDC00)
+ end
+ t[k] = v
+ return v
+ end)
+
+ local unified = Cs(Cc("<feff") * (lpeg.patterns.utf8character/cache)^1 * Cc(">"))
+
+ tosixteen = function(str) -- an lpeg might be faster (no table)
+ if not str or str == "" then
+ return "<feff>" -- not () as we want an indication that it's unicode
+ else
+ return lpegmatch(unified,str)
+ end
end
- t[k] = v
- return v
-end)
-local escaped = Cs(Cc("(") * (S("\\()")/"\\%0" + P(1))^0 * Cc(")"))
-local unified = Cs(Cc("<feff") * (lpeg.patterns.utf8character/cache)^1 * Cc(">"))
+ local more = 0
-local function tosixteen(str) -- an lpeg might be faster (no table)
- if not str or str == "" then
- return "<feff>" -- not () as we want an indication that it's unicode
- else
- return lpegmatch(unified,str)
+ local pattern = C(4) / function(s) -- needs checking !
+ local now = tonumber(s,16)
+ if more > 0 then
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
+ more = 0
+ return utfchar(now)
+ elseif now >= 0xD800 and now <= 0xDBFF then
+ more = now
+ return "" -- else the c's end up in the stream
+ else
+ return utfchar(now)
+ end
end
-end
-local more = 0
-
-local pattern = C(4) / function(s) -- needs checking !
- local now = tonumber(s,16)
- if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
- more = 0
- return utfchar(now)
- elseif now >= 0xD800 and now <= 0xDBFF then
- more = now
- return "" -- else the c's end up in the stream
- else
- return utfchar(now)
+ local pattern = P(true) / function() more = 0 end * Cs(pattern^0)
+
+ fromsixteen = function(str)
+ if not str or str == "" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
end
-end
-local pattern = P(true) / function() more = 0 end * Cs(pattern^0)
+ local toregime = regimes.toregime
+ local fromregime = regimes.fromregime
-local function fromsixteen(str)
- if not str or str == "" then
- return ""
- else
- return lpegmatch(pattern,str)
+ topdfdoc = function(str,default)
+ if not str or str == "" then
+ return ""
+ else
+ return lpegmatch(escaped,toregime("pdfdoc",str,default)) -- could be combined if needed
+ end
end
-end
-local toregime = regimes.toregime
-local fromregime = regimes.fromregime
+ frompdfdoc = function(str)
+ if not str or str == "" then
+ return ""
+ else
+ return fromregime("pdfdoc",str)
+ end
+ end
-local function topdfdoc(str,default)
- if not str or str == "" then
- return ""
- else
- return lpegmatch(escaped,toregime("pdfdoc",str,default)) -- could be combined if needed
+ if not toregime then topdfdoc = function(s) return s end end
+ if not fromregime then frompdfdoc = function(s) return s end end
+
+ toeight = function(str)
+ if not str or str == "" then
+ return "()"
+ else
+ return lpegmatch(escaped,str)
+ end
end
-end
-local function frompdfdoc(str)
- if not str or str == "" then
- return ""
- else
- return fromregime("pdfdoc",str)
+ local b_pattern = Cs((P("\\")/"" * (
+ S("()")
+ + S("nrtbf") / { n = "\n", r = "\r", t = "\t", b = "\b", f = "\f" }
+ + lpegpatterns.octdigit^-3 / function(s) return char(tonumber(s,8)) end)
+ + P(1))^0)
+
+ fromeight = function(str)
+ if not str or str == "" then
+ return ""
+ else
+ return lpegmatch(unescape,str)
+ end
end
-end
-if not toregime then topdfdoc = function(s) return s end end
-if not fromregime then frompdfdoc = function(s) return s end end
+ local u_pattern = lpegpatterns.utfbom_16_be * lpegpatterns.utf16_to_utf8_be -- official
+ + lpegpatterns.utfbom_16_le * lpegpatterns.utf16_to_utf8_le -- we've seen these
+
+ local h_pattern = lpegpatterns.hextobytes
+
+ local zero = S(" \n\r\t") + P("\\ ")
+ local one = C(4)
+ local two = P("d") * R("89","af") * C(2) * C(4)
+
+ local x_pattern = P { "start",
+ start = V("wrapped") + V("unwrapped") + V("original"),
+ original = Cs(P(1)^0),
+ wrapped = P("<") * V("unwrapped") * P(">") * P(-1),
+ unwrapped = P("feff")
+ * Cs( (
+ zero / ""
+ + two / function(a,b)
+ a = (tonumber(a,16) - 0xD800) * 1024
+ b = (tonumber(b,16) - 0xDC00)
+ return utfchar(a+b)
+ end
+ + one / function(a)
+ return utfchar(tonumber(a,16))
+ end
+ )^1 ) * P(-1)
+ }
-local function toeight(str)
- if not str or str == "" then
- return "()"
- else
- return lpegmatch(escaped,str)
+ function lpdf.frombytes(s,hex)
+ if not s or s == "" then
+ return ""
+ end
+ if hex then
+ local x = lpegmatch(x_pattern,s)
+ if x then
+ return x
+ end
+ local h = lpegmatch(h_pattern,s)
+ if h then
+ return h
+ end
+ else
+ local u = lpegmatch(u_pattern,s)
+ if u then
+ return u
+ end
+ end
+ return lpegmatch(b_pattern,s)
end
-end
-lpdf.tosixteen = tosixteen
-lpdf.toeight = toeight
-lpdf.topdfdoc = topdfdoc
-lpdf.fromsixteen = fromsixteen
-lpdf.frompdfdoc = frompdfdoc
-
-local function merge_t(a,b)
- local t = { }
- for k,v in next, a do t[k] = v end
- for k,v in next, b do t[k] = v end
- return setmetatable(t,getmetatable(a))
-end
+ lpdf.tosixteen = tosixteen
+ lpdf.toeight = toeight
+ lpdf.topdfdoc = topdfdoc
+ lpdf.fromsixteen = fromsixteen
+ lpdf.fromeight = fromeight
+ lpdf.frompdfdoc = frompdfdoc
-local f_key_null = formatters["/%s null"]
-local f_key_value = formatters["/%s %s"]
-local f_key_dictionary = formatters["/%s << % t >>"]
-local f_dictionary = formatters["<< % t >>"]
-local f_key_array = formatters["/%s [ % t ]"]
-local f_array = formatters["[ % t ]"]
-local f_key_number = formatters["/%s %F"]
-local f_tonumber = formatters["%F"]
+end
local tostring_a, tostring_d
-tostring_d = function(t,contentonly,key)
- if next(t) then
- local r, n = { }, 0
- for k in next, t do
- n = n + 1
- r[n] = k
- end
- sort(r)
- for i=1,n do
- local k = r[i]
- local v = t[k]
- local tv = type(v)
- if tv == "string" then
- r[i] = f_key_value(k,toeight(v))
- elseif tv == "number" then
- r[i] = f_key_number(k,v)
- -- elseif tv == "unicode" then -- can't happen
- -- r[i] = f_key_value(k,tosixteen(v))
- elseif tv == "table" then
- local mv = getmetatable(v)
- if mv and mv.__lpdftype then
- -- if v == t then
- -- report_objects("ignoring circular reference in dirctionary")
- -- r[i] = f_key_null(k)
- -- else
- r[i] = f_key_value(k,tostring(v))
- -- end
- elseif v[1] then
- r[i] = f_key_value(k,tostring_a(v))
+do
+
+ local f_key_null = formatters["/%s null"]
+ local f_key_value = formatters["/%s %s"]
+ local f_key_dictionary = formatters["/%s << % t >>"]
+ local f_dictionary = formatters["<< % t >>"]
+ local f_key_array = formatters["/%s [ % t ]"]
+ local f_array = formatters["[ % t ]"]
+ local f_key_number = formatters["/%s %N"] -- always with max 9 digits and integer is possible
+ local f_tonumber = formatters["%N"] -- always with max 9 digits and integer is possible
+
+ tostring_d = function(t,contentonly,key)
+ if next(t) then
+ local r = { }
+ local n = 0
+ local e
+ for k, v in next, t do
+ if k == "__extra__" then
+ e = v
+ elseif k == "__stream__" then
+ -- do nothing (yet)
else
- r[i] = f_key_value(k,tostring_d(v))
+ n = n + 1
+ r[n] = k
end
+ end
+ if n > 1 then
+ sort(r)
+ end
+ for i=1,n do
+ local k = r[i]
+ local v = t[k]
+ local tv = type(v)
+ -- mostly tables
+ if tv == "table" then
+ -- local mv = getmetatable(v)
+ -- if mv and mv.__lpdftype then
+ if v.__lpdftype__ then
+ -- if v == t then
+ -- report_objects("ignoring circular reference in dirctionary")
+ -- r[i] = f_key_null(k)
+ -- else
+ r[i] = f_key_value(k,tostring(v))
+ -- end
+ elseif v[1] then
+ r[i] = f_key_value(k,tostring_a(v))
+ else
+ r[i] = f_key_value(k,tostring_d(v))
+ end
+ elseif tv == "string" then
+ r[i] = f_key_value(k,toeight(v))
+ elseif tv == "number" then
+ r[i] = f_key_number(k,v)
+ else
+ r[i] = f_key_value(k,tostring(v))
+ end
+ end
+ if e then
+ r[n+1] = e
+ end
+ if contentonly then
+ return concat(r," ")
+ elseif key then
+ return f_key_dictionary(key,r)
else
- r[i] = f_key_value(k,tostring(v))
+ return f_dictionary(r)
end
- end
- if contentonly then
- return concat(r," ")
- elseif key then
- return f_key_dictionary(key,r)
+ elseif contentonly then
+ return ""
else
- return f_dictionary(r)
+ return "<< >>"
end
- elseif contentonly then
- return ""
- else
- return "<< >>"
end
-end
-tostring_a = function(t,contentonly,key)
- local tn = #t
- if tn ~= 0 then
- local r = { }
- for k=1,tn do
- local v = t[k]
- local tv = type(v)
- if tv == "string" then
- r[k] = toeight(v)
- elseif tv == "number" then
- r[k] = f_tonumber(v)
- -- elseif tv == "unicode" then
- -- r[k] = tosixteen(v)
- elseif tv == "table" then
- local mv = getmetatable(v)
- local mt = mv and mv.__lpdftype
- if mt then
- -- if v == t then
- -- report_objects("ignoring circular reference in array")
- -- r[k] = "null"
- -- else
- r[k] = tostring(v)
- -- end
- elseif v[1] then
- r[k] = tostring_a(v)
+ tostring_a = function(t,contentonly,key)
+ local tn = #t
+ if tn ~= 0 then
+ local r = { }
+ for k=1,tn do
+ local v = t[k]
+ local tv = type(v)
+ -- mostly numbers and tables
+ if tv == "number" then
+ r[k] = f_tonumber(v)
+ elseif tv == "table" then
+ -- local mv = getmetatable(v)
+ -- if mv and mv.__lpdftype then
+ if v.__lpdftype__ then
+ -- if v == t then
+ -- report_objects("ignoring circular reference in array")
+ -- r[k] = "null"
+ -- else
+ r[k] = tostring(v)
+ -- end
+ elseif v[1] then
+ r[k] = tostring_a(v)
+ else
+ r[k] = tostring_d(v)
+ end
+ elseif tv == "string" then
+ r[k] = toeight(v)
else
- r[k] = tostring_d(v)
+ r[k] = tostring(v)
end
+ end
+ local e = t.__extra__
+ if e then
+ r[tn+1] = e
+ end
+ if contentonly then
+ return concat(r, " ")
+ elseif key then
+ return f_key_array(key,r)
else
- r[k] = tostring(v)
+ return f_array(r)
end
- end
- if contentonly then
- return concat(r, " ")
- elseif key then
- return f_key_array(key,r)
+ elseif contentonly then
+ return ""
else
- return f_array(r)
+ return "[ ]"
end
- elseif contentonly then
- return ""
- else
- return "[ ]"
end
+
end
+local f_tonumber = formatters["%N"]
+
local tostring_x = function(t) return concat(t," ") end
local tostring_s = function(t) return toeight(t[1]) end
local tostring_p = function(t) return topdfdoc(t[1],t[2]) end
@@ -484,6 +588,17 @@ local tostring_v = function(t)
end
end
+local tostring_l = function(t)
+ local s = t[1]
+ if not s or s == "" then
+ return "()"
+ elseif t[2] then
+ return "<" .. s .. ">"
+ else
+ return "(" .. s .. ")"
+ end
+end
+
local function value_x(t) return t end
local function value_s(t) return t[1] end
local function value_p(t) return t[1] end
@@ -495,24 +610,75 @@ local function value_a(t) return tostring_a(t,true) end
local function value_z() return nil end
local function value_t(t) return t.value or true end
local function value_f(t) return t.value or false end
-local function value_r() return t[1] or 0 end -- null
-local function value_v() return t[1] end
+local function value_r(t) return t[1] or 0 end -- null
+local function value_v(t) return t[1] end
+local function value_l(t) return t[1] end
+
+local function add_to_d(t,v)
+ local k = type(v)
+ if k == "string" then
+ if t.__extra__ then
+ t.__extra__ = t.__extra__ .. " " .. v
+ else
+ t.__extra__ = v
+ end
+ elseif k == "table" then
+ for k, v in next, v do
+ t[k] = v
+ end
+ end
+ return t
+end
+
+local function add_to_a(t,v)
+ local k = type(v)
+ if k == "string" then
+ if t.__extra__ then
+ t.__extra__ = t.__extra__ .. " " .. v
+ else
+ t.__extra__ = v
+ end
+ elseif k == "table" then
+ local n = #t
+ for i=1,#v do
+ n = n + 1
+ t[n] = v[i]
+ end
+ end
+ return t
+end
local function add_x(t,k,v) rawset(t,k,tostring(v)) end
-local mt_x = { __lpdftype = "stream", __tostring = tostring_x, __call = value_x, __newindex = add_x }
-local mt_d = { __lpdftype = "dictionary", __tostring = tostring_d, __call = value_d }
-local mt_a = { __lpdftype = "array", __tostring = tostring_a, __call = value_a }
-local mt_u = { __lpdftype = "unicode", __tostring = tostring_u, __call = value_u }
-local mt_s = { __lpdftype = "string", __tostring = tostring_s, __call = value_s }
-local mt_p = { __lpdftype = "docstring", __tostring = tostring_p, __call = value_p }
-local mt_n = { __lpdftype = "number", __tostring = tostring_n, __call = value_n }
-local mt_c = { __lpdftype = "constant", __tostring = tostring_c, __call = value_c }
-local mt_z = { __lpdftype = "null", __tostring = tostring_z, __call = value_z }
-local mt_t = { __lpdftype = "true", __tostring = tostring_t, __call = value_t }
-local mt_f = { __lpdftype = "false", __tostring = tostring_f, __call = value_f }
-local mt_r = { __lpdftype = "reference", __tostring = tostring_r, __call = value_r }
-local mt_v = { __lpdftype = "verbose", __tostring = tostring_v, __call = value_v }
+-- local mt_x = { __index = { __lpdftype__ = "stream" }, __lpdftype = "stream", __tostring = tostring_x, __call = value_x, __newindex = add_x }
+-- local mt_d = { __index = { __lpdftype__ = "dictionary" }, __lpdftype = "dictionary", __tostring = tostring_d, __call = value_d, __add = add_to_d }
+-- local mt_a = { __index = { __lpdftype__ = "array" }, __lpdftype = "array", __tostring = tostring_a, __call = value_a, __add = add_to_a }
+-- local mt_u = { __index = { __lpdftype__ = "unicode" }, __lpdftype = "unicode", __tostring = tostring_u, __call = value_u }
+-- local mt_s = { __index = { __lpdftype__ = "string" }, __lpdftype = "string", __tostring = tostring_s, __call = value_s }
+-- local mt_p = { __index = { __lpdftype__ = "docstring" }, __lpdftype = "docstring", __tostring = tostring_p, __call = value_p }
+-- local mt_n = { __index = { __lpdftype__ = "number" }, __lpdftype = "number", __tostring = tostring_n, __call = value_n }
+-- local mt_c = { __index = { __lpdftype__ = "constant" }, __lpdftype = "constant", __tostring = tostring_c, __call = value_c }
+-- local mt_z = { __index = { __lpdftype__ = "null" }, __lpdftype = "null", __tostring = tostring_z, __call = value_z }
+-- local mt_t = { __index = { __lpdftype__ = "true" }, __lpdftype = "true", __tostring = tostring_t, __call = value_t }
+-- local mt_f = { __index = { __lpdftype__ = "false" }, __lpdftype = "false", __tostring = tostring_f, __call = value_f }
+-- local mt_r = { __index = { __lpdftype__ = "reference" }, __lpdftype = "reference", __tostring = tostring_r, __call = value_r }
+-- local mt_v = { __index = { __lpdftype__ = "verbose" }, __lpdftype = "verbose", __tostring = tostring_v, __call = value_v }
+-- local mt_l = { __index = { __lpdftype__ = "literal" }, __lpdftype = "literal", __tostring = tostring_l, __call = value_l }
+
+local mt_x = { __index = { __lpdftype__ = "stream" }, __tostring = tostring_x, __call = value_x, __newindex = add_x }
+local mt_d = { __index = { __lpdftype__ = "dictionary" }, __tostring = tostring_d, __call = value_d, __add = add_to_d }
+local mt_a = { __index = { __lpdftype__ = "array" }, __tostring = tostring_a, __call = value_a, __add = add_to_a }
+local mt_u = { __index = { __lpdftype__ = "unicode" }, __tostring = tostring_u, __call = value_u }
+local mt_s = { __index = { __lpdftype__ = "string" }, __tostring = tostring_s, __call = value_s }
+local mt_p = { __index = { __lpdftype__ = "docstring" }, __tostring = tostring_p, __call = value_p }
+local mt_n = { __index = { __lpdftype__ = "number" }, __tostring = tostring_n, __call = value_n }
+local mt_c = { __index = { __lpdftype__ = "constant" }, __tostring = tostring_c, __call = value_c }
+local mt_z = { __index = { __lpdftype__ = "null" }, __tostring = tostring_z, __call = value_z }
+local mt_t = { __index = { __lpdftype__ = "true" }, __tostring = tostring_t, __call = value_t }
+local mt_f = { __index = { __lpdftype__ = "false" }, __tostring = tostring_f, __call = value_f }
+local mt_r = { __index = { __lpdftype__ = "reference" }, __tostring = tostring_r, __call = value_r }
+local mt_v = { __index = { __lpdftype__ = "verbose" }, __tostring = tostring_v, __call = value_v }
+local mt_l = { __index = { __lpdftype__ = "literal" }, __tostring = tostring_l, __call = value_l }
local function pdfstream(t) -- we need to add attributes
if t then
@@ -522,9 +688,9 @@ local function pdfstream(t) -- we need to add attributes
t[i] = tostring(t[i])
end
elseif tt == "string" then
- t= { t }
+ t = { t }
else
- t= { tostring(t) }
+ t = { tostring(t) }
end
end
return setmetatable(t or { },mt_x)
@@ -554,46 +720,70 @@ local function pdfunicode(str,default)
return setmetatable({ str or default or "" },mt_u) -- could be a string
end
-local cache = { } -- can be weak
-
-local function pdfnumber(n,default) -- 0-10
- n = n or default
- local c = cache[n]
- if not c then
- c = setmetatable({ n },mt_n)
- -- cache[n] = c -- too many numbers
- end
- return c
+local function pdfliteral(str,hex) -- can also produce a hex <> instead of () literal
+ return setmetatable({ str, hex },mt_l)
end
-for i=-1,9 do cache[i] = pdfnumber(i) end
+local pdfnumber, pdfconstant
-local cache = { } -- can be weak
+do
-local forbidden, replacements = "\0\t\n\r\f ()[]{}/%%#\\", { } -- table faster than function
+ local cache = { } -- can be weak
-for s in gmatch(forbidden,".") do
- replacements[s] = format("#%02x",byte(s))
-end
+ pdfnumber = function(n,default) -- 0-10
+ if not n then
+ n = default
+ end
+ local c = cache[n]
+ if not c then
+ c = setmetatable({ n },mt_n)
+ -- cache[n] = c -- too many numbers
+ end
+ return c
+ end
+
+ for i=-1,9 do cache[i] = pdfnumber(i) end
+
+ local replacer = S("\0\t\n\r\f ()[]{}/%%#\\") / {
+ ["\00"]="#00",
+ ["\09"]="#09",
+ ["\10"]="#0a",
+ ["\12"]="#0c",
+ ["\13"]="#0d",
+ [ " " ]="#20",
+ [ "#" ]="#23",
+ [ "%" ]="#25",
+ [ "(" ]="#28",
+ [ ")" ]="#29",
+ [ "/" ]="#2f",
+ [ "[" ]="#5b",
+ [ "\\"]="#5c",
+ [ "]" ]="#5d",
+ [ "{" ]="#7b",
+ [ "}" ]="#7d",
+ } + P(1)
+
+ local escaped = Cs(Cc("/") * replacer^0)
+
+ local cache = table.setmetatableindex(function(t,k)
+ local v = setmetatable({ lpegmatch(escaped,k) }, mt_c)
+ t[k] = v
+ return v
+ end)
+
+ pdfconstant = function(str,default)
+ if not str then
+ str = default or "none"
+ end
+ return cache[str]
+ end
-local escaped = Cs(Cc("/") * (S(forbidden)/replacements + P(1))^0)
+ local escaped = Cs(replacer^0)
-local function pdfconstant(str,default)
- str = str or default or ""
- local c = cache[str]
- if not c then
- -- c = setmetatable({ "/" .. str },mt_c)
- c = setmetatable({ lpegmatch(escaped,str) },mt_c)
- cache[str] = c
+ function lpdf.escaped(str)
+ return lpegmatch(escaped,str) or str
end
- return c
-end
-local escaped = Cs((S(forbidden)/replacements + P(1))^0)
------ escaped = Cs((1-forbidden)^0 * S(forbidden)/replacements * ((S(forbidden)/replacements + P(1))^0)
-
-function lpdf.escaped(str)
- return lpegmatch(escaped,str) or str
end
local pdfnull, pdfboolean, pdfreference, pdfverbose
@@ -657,6 +847,7 @@ lpdf.null = pdfnull
lpdf.boolean = pdfboolean
lpdf.reference = pdfreference
lpdf.verbose = pdfverbose
+lpdf.literal = pdfliteral
local names, cache = { }, { }
@@ -673,13 +864,7 @@ function lpdf.reserveobject(name)
return r
end
--- lpdf.reserveobject = pdfreserveobject
--- lpdf.immediateobject = pdfimmediateobject
--- lpdf.deferredobject = pdfdeferredobject
--- lpdf.referenceobject = pdfreferenceobject
-
-local pagereference = pdf.pageref -- tex.pdfpageref is obsolete
-local nofpages = 0
+local nofpages = 0
function lpdf.pagereference(n)
if nofpages == 0 then
@@ -689,12 +874,24 @@ function lpdf.pagereference(n)
end
end
if n > nofpages then
- return pagereference(nofpages) -- or 1, could be configureable
+ return pdfgetpagereference(nofpages) -- or 1, could be configureable
else
- return pagereference(n)
+ return pdfgetpagereference(n)
end
end
+function lpdf.nofpages()
+ return structures.pages.nofpages
+end
+
+function lpdf.obj(...)
+ pdfdeferredobject(...)
+end
+
+function lpdf.immediateobj(...)
+ pdfimmediateobject(...)
+end
+
function lpdf.delayedobject(data,n)
if n then
pdfdeferredobject(n,data)
@@ -733,14 +930,22 @@ function lpdf.flushobject(name,data)
end
end
-
-function lpdf.flushstreamobject(data,dict,compressed) -- default compressed
+function lpdf.flushstreamobject(data,dict,compressed,objnum) -- default compressed
if trace_objects then
report_objects("flushing stream object of %s bytes",#data)
end
- local dtype = type(dict)
+ local dtype = type(dict)
+ local kind = compressed == "raw" and "raw" or "stream"
+ local nolength = nil
+ if compressed == "raw" then
+ compressed = nil
+ nolength = true
+ -- data = string.formatters["<< %s >>stream\n%s\nendstream"](attr,data)
+ end
return pdfdeferredobject {
+ objnum = objnum,
immediate = true,
+ nolength = nolength,
compresslevel = compressed == false and 0 or nil,
type = "stream",
string = data,
@@ -748,12 +953,13 @@ function lpdf.flushstreamobject(data,dict,compressed) -- default compressed
}
end
-function lpdf.flushstreamfileobject(filename,dict,compressed) -- default compressed
+function lpdf.flushstreamfileobject(filename,dict,compressed,objnum) -- default compressed
if trace_objects then
report_objects("flushing stream file object %a",filename)
end
local dtype = type(dict)
return pdfdeferredobject {
+ objnum = objnum,
immediate = true,
compresslevel = compressed == false and 0 or nil,
type = "stream",
@@ -810,6 +1016,14 @@ local function resetpageproperties()
pagesattributes = pdfdictionary()
end
+function lpdf.getpageproperties()
+ return {
+ pageresources = pageresources,
+ pageattributes = pageattributes,
+ pagesattributes = pagesattributes,
+ }
+end
+
resetpageproperties()
local function setpageproperties()
@@ -882,37 +1096,28 @@ function lpdf.finalizedocument()
if not environment.initex then
run(documentfinalizers,"document")
function lpdf.finalizedocument()
- report_finalizing("serious error: the document is finalized multiple times")
+ -- report_finalizing("serious error: the document is finalized multiple times")
function lpdf.finalizedocument() end
end
end
end
--- codeinjections.finalizepage = lpdf.finalizepage -- no longer triggered at the tex end
-
-if not callbacks.register("finish_pdfpage", lpdf.finalizepage) then
-
- local find_tail = nodes.tail
- local latelua_node = nodes.pool.latelua
-
- function nodeinjections.finalizepage(head)
- local t = find_tail(head.list)
- if t then
- local n = latelua_node("lpdf.finalizepage(true)") -- last in the shipout
- t.next = n
- n.prev = t
- end
- return head, true
- end
-
- nodes.tasks.appendaction("shipouts","normalizers","backends.pdf.nodeinjections.finalizepage")
+callbacks.register("finish_pdfpage", lpdf.finalizepage)
+callbacks.register("finish_pdffile", lpdf.finalizedocument)
-end
+do
-callbacks.register("finish_pdffile", lpdf.finalizedocument)
+ local pdfsetinfo, pdfsetcatalog, pdfsettrailerid -- pdfsetnames pdfsettrailer
+ updaters.register("backend.update.lpdf",function()
+ pdfsetinfo = pdf.setinfo
+ pdfsetcatalog = pdf.setcatalog
+ pdfsettrailerid = pdf.settrailerid
+ end)
-do
+ function lpdf.settrailerid(id)
+ pdfsettrailerid(id)
+ end
-- some minimal tracing, handy for checking the order
@@ -934,18 +1139,16 @@ do
local info = pdfdictionary { Type = pdfconstant("Info") } -- nicer, but when we assign we nil the Type
----- names = pdfdictionary { Type = pdfconstant("Names") } -- nicer, but when we assign we nil the Type
- local function flushcatalog()
+ local function checkcatalog()
if not environment.initex then
trace_flush("catalog")
- catalog.Type = nil
- pdfsetcatalog(catalog())
+ return true
end
end
- local function flushinfo()
+ local function checkinfo()
if not environment.initex then
trace_flush("info")
- info.Type = nil
if lpdf.majorversion() > 1 then
for k, v in next, info do
if k == "CreationDate" or k == "ModDate" then
@@ -955,17 +1158,36 @@ do
end
end
end
+ return true
+ end
+ end
+
+ local function flushcatalog()
+ if checkcatalog() then
+ catalog.Type = nil
+ pdfsetcatalog(catalog())
+ end
+ end
+
+ local function flushinfo()
+ if checkinfo() then
+ info.Type = nil
pdfsetinfo(info())
end
end
- -- local function flushnames()
- -- if not environment.initex then
- -- trace_flush("names")
- -- names.Type = nil
- -- pdfsetnames(names())
- -- end
- -- end
+ function lpdf.getcatalog()
+ if checkcatalog() then
+ catalog.Type = pdfconstant("Catalog")
+ return pdfreference(pdfimmediateobject(tostring(catalog)))
+ end
+ end
+
+ function lpdf.getinfo()
+ if checkinfo() then
+ return pdfreference(pdfimmediateobject(tostring(info)))
+ end
+ end
function lpdf.addtocatalog(k,v)
if not (lpdf.protectresources and catalog[k]) then
@@ -1007,20 +1229,19 @@ do
end
end
- local r_extgstates, d_extgstates = pdfreserveobject(), pdfdictionary() local p_extgstates = pdfreference(r_extgstates)
- local r_colorspaces, d_colorspaces = pdfreserveobject(), pdfdictionary() local p_colorspaces = pdfreference(r_colorspaces)
- local r_patterns, d_patterns = pdfreserveobject(), pdfdictionary() local p_patterns = pdfreference(r_patterns)
- local r_shades, d_shades = pdfreserveobject(), pdfdictionary() local p_shades = pdfreference(r_shades)
+ local r_extgstates, r_colorspaces, r_patterns, r_shades
+ local d_extgstates, d_colorspaces, d_patterns, d_shades
+ local p_extgstates, p_colorspaces, p_patterns, p_shades
- local function checkextgstates () if next(d_extgstates ) then addtopageresources("ExtGState", p_extgstates ) end end
- local function checkcolorspaces() if next(d_colorspaces) then addtopageresources("ColorSpace",p_colorspaces) end end
- local function checkpatterns () if next(d_patterns ) then addtopageresources("Pattern", p_patterns ) end end
- local function checkshades () if next(d_shades ) then addtopageresources("Shading", p_shades ) end end
+ local function checkextgstates () if d_extgstates then addtopageresources("ExtGState", p_extgstates ) end end
+ local function checkcolorspaces() if d_colorspaces then addtopageresources("ColorSpace",p_colorspaces) end end
+ local function checkpatterns () if d_patterns then addtopageresources("Pattern", p_patterns ) end end
+ local function checkshades () if d_shades then addtopageresources("Shading", p_shades ) end end
- local function flushextgstates () if next(d_extgstates ) then trace_flush("extgstates") pdfimmediateobject(r_extgstates, tostring(d_extgstates )) end end
- local function flushcolorspaces() if next(d_colorspaces) then trace_flush("colorspaces") pdfimmediateobject(r_colorspaces,tostring(d_colorspaces)) end end
- local function flushpatterns () if next(d_patterns ) then trace_flush("patterns") pdfimmediateobject(r_patterns, tostring(d_patterns )) end end
- local function flushshades () if next(d_shades ) then trace_flush("shades") pdfimmediateobject(r_shades, tostring(d_shades )) end end
+ local function flushextgstates () if d_extgstates then trace_flush("extgstates") pdfimmediateobject(r_extgstates, tostring(d_extgstates )) end end
+ local function flushcolorspaces() if d_colorspaces then trace_flush("colorspaces") pdfimmediateobject(r_colorspaces,tostring(d_colorspaces)) end end
+ local function flushpatterns () if d_patterns then trace_flush("patterns") pdfimmediateobject(r_patterns, tostring(d_patterns )) end end
+ local function flushshades () if d_shades then trace_flush("shades") pdfimmediateobject(r_shades, tostring(d_shades )) end end
-- patterns are special as they need resources to so we can get recursive references and in that case
-- acrobat doesn't show anything (other viewers handle it well)
@@ -1029,10 +1250,10 @@ do
-- todo: force when not yet set
function lpdf.collectedresources(options)
- local ExtGState = next(d_extgstates ) and p_extgstates
- local ColorSpace = next(d_colorspaces) and p_colorspaces
- local Pattern = next(d_patterns ) and p_patterns
- local Shading = next(d_shades ) and p_shades
+ local ExtGState = d_extgstates and next(d_extgstates ) and p_extgstates
+ local ColorSpace = d_colorspaces and next(d_colorspaces) and p_colorspaces
+ local Pattern = d_patterns and next(d_patterns ) and p_patterns
+ local Shading = d_shades and next(d_shades ) and p_shades
if options and options.patterns == false then
Pattern = nil
end
@@ -1042,18 +1263,56 @@ do
ColorSpace = ColorSpace,
Pattern = Pattern,
Shading = Shading,
- -- ProcSet = pdfarray { pdfconstant("PDF") },
}
- return collected()
+ if options and options.serialize == false then
+ return collected
+ else
+ return collected()
+ end
else
- return ""
+ if options and options.serialize == false then
+ return pdfdictionary { }
+ else
+ return ""
+ end
end
end
- function lpdf.adddocumentextgstate (k,v) d_extgstates [k] = v end
- function lpdf.adddocumentcolorspace(k,v) d_colorspaces[k] = v end
- function lpdf.adddocumentpattern (k,v) d_patterns [k] = v end
- function lpdf.adddocumentshade (k,v) d_shades [k] = v end
+ function lpdf.adddocumentextgstate (k,v)
+ if not d_extgstates then
+ r_extgstates = pdfreserveobject()
+ d_extgstates = pdfdictionary()
+ p_extgstates = pdfreference(r_extgstates)
+ end
+ d_extgstates[k] = v
+ end
+
+ function lpdf.adddocumentcolorspace(k,v)
+ if not d_colorspaces then
+ r_colorspaces = pdfreserveobject()
+ d_colorspaces = pdfdictionary()
+ p_colorspaces = pdfreference(r_colorspaces)
+ end
+ d_colorspaces[k] = v
+ end
+
+ function lpdf.adddocumentpattern(k,v)
+ if not d_patterns then
+ r_patterns = pdfreserveobject()
+ d_patterns = pdfdictionary()
+ p_patterns = pdfreference(r_patterns)
+ end
+ d_patterns[k] = v
+ end
+
+ function lpdf.adddocumentshade(k,v)
+ if not d_shades then
+ r_shades = pdfreserveobject()
+ d_shades = pdfdictionary()
+ p_shades = pdfreference(r_shades)
+ end
+ d_shades[k] = v
+ end
registerdocumentfinalizer(flushextgstates,3,"extended graphic states")
registerdocumentfinalizer(flushcolorspaces,3,"color spaces")
@@ -1074,7 +1333,8 @@ end
-- in strc-bkm: lpdf.registerdocumentfinalizer(function() structures.bookmarks.place() end,1)
function lpdf.rotationcm(a)
- local s, c = sind(a), cosd(a)
+ local s = sind(a)
+ local c = cosd(a)
return format("%.6F %.6F %.6F %.6F 0 0 cm",c,s,-s,c)
end
@@ -1127,12 +1387,12 @@ do
return Y and format("D:%s%s%s%s%s%s%s%s'%s'",Y,M,D,h,m,s,Zs,Zh,Zm)
end
- function lpdf.id(nodate)
+ function lpdf.id(date)
local banner = environment.jobname or tex.jobname or "unknown"
- if nodate then
+ if not date then
return banner
else
- return format("%s.%s",banner,timestamp)
+ return format("%s | %s",banner,timestamp)
end
end
@@ -1190,7 +1450,6 @@ function lpdf.checkedvalue(value,variant) -- code not shared
end
end
end
- -- return nil
end
function lpdf.limited(n,min,max,default)
@@ -1210,61 +1469,6 @@ function lpdf.limited(n,min,max,default)
end
end
--- if not pdfreferenceobject then
---
--- local delayed = { }
---
--- local function flush()
--- local n = 0
--- for k,v in next, delayed do
--- pdfimmediateobject(k,v)
--- n = n + 1
--- end
--- if trace_objects then
--- report_objects("%s objects flushed",n)
--- end
--- delayed = { }
--- end
---
--- lpdf.registerdocumentfinalizer(flush,3,"objects") -- so we need a final flush too
--- lpdf.registerpagefinalizer (flush,3,"objects") -- somehow this lags behind .. I need to look into that some day
---
--- function lpdf.delayedobject(data)
--- local n = pdfreserveobject()
--- delayed[n] = data
--- return n
--- end
---
--- end
-
--- setmetatable(pdf, {
--- __index = function(t,k)
--- if k == "info" then return pdf.getinfo()
--- elseif k == "catalog" then return pdf.getcatalog()
--- elseif k == "names" then return pdf.getnames()
--- elseif k == "trailer" then return pdf.gettrailer()
--- elseif k == "pageattribute" then return pdf.getpageattribute()
--- elseif k == "pageattributes" then return pdf.getpageattributes()
--- elseif k == "pageresources" then return pdf.getpageresources()
--- elseif
--- return nil
--- end
--- end,
--- __newindex = function(t,k,v)
--- if k == "info" then return pdf.setinfo(v)
--- elseif k == "catalog" then return pdf.setcatalog(v)
--- elseif k == "names" then return pdf.setnames(v)
--- elseif k == "trailer" then return pdf.settrailer(v)
--- elseif k == "pageattribute" then return pdf.setpageattribute(v)
--- elseif k == "pageattributes" then return pdf.setpageattributes(v)
--- elseif k == "pageresources" then return pdf.setpageresources(v)
--- else
--- rawset(t,k,v)
--- end
--- end,
--- })
-
-
-- The next variant of ActualText is what Taco and I could come up with
-- eventually. As of September 2013 Acrobat copies okay, Sumatra copies a
-- question mark, pdftotext injects an extra space and Okular adds a
@@ -1287,7 +1491,7 @@ do
local f_actual_text = formatters["/Span <</ActualText %s >> BDC"]
local context = context
- local pdfdirect = nodes.pool.pdfdirectliteral
+ local pdfdirect = nodes.pool.directliteral -- we can use nuts.write deep down
-- todo: use tounicode from the font mapper
@@ -1383,11 +1587,9 @@ end
function lpdf.copyarray(a)
if a then
local t = pdfarray()
- local k = a.__kind
for i=1,#a do
t[i] = a(i)
end
--- inspect(t)
return t
end
end
@@ -1398,7 +1600,6 @@ function lpdf.copydictionary(d)
for k, v in next, d do
t[k] = d(k)
end
--- inspect(t)
return t
end
end
@@ -1420,3 +1621,73 @@ function lpdf.copystring(v)
return pdfstring(v)
end
end
+
+do
+
+ local pdfincludechar, pdfincludecharlist, pdfincludefont
+ local pdfgetfontname, pdfgetfontobjnum
+ local pdfsetmapfile, pdfsetmapline
+
+ updaters.register("backend.update.lpdf",function()
+ pdfincludechar = pdf.includechar
+ pdfincludefont = pdf.includefont
+ pdfincludecharlist = pdf.includecharlist
+ pdfgetfontname = pdf.getfontname
+ pdfgetfontobjnum = pdf.getfontobjnum
+ pdfsetmapfile = pdf.mapfile
+ pdfsetmapline = pdf.mapline
+ end)
+
+ function lpdf.includechar(f,c) pdfincludechar(f,c) end
+ function lpdf.includefont(...) pdfincludefont(...) end
+
+ function lpdf.includecharlist(f,c) pdfincludecharlist(f,c) end -- can be disabled
+
+ function lpdf.getfontname (id) return pdfgetfontname (id) end
+ function lpdf.getfontobjnumber(id) return pdfgetfontobjnum(id) end
+
+ function lpdf.setmapfile(...) pdfsetmapfile(...) end
+ function lpdf.setmapline(...) pdfsetmapline(...) end
+
+end
+
+do
+
+ -- This is obsolete but old viewers might still use it as directive
+ -- for what to send to a postscript printer.
+
+ local a_procset, d_procset
+
+ function lpdf.procset(dict)
+ if not a_procset then
+ a_procset = pdfarray {
+ pdfconstant("PDF"),
+ pdfconstant("Text"),
+ pdfconstant("ImageB"),
+ pdfconstant("ImageC"),
+ pdfconstant("ImageI"),
+ }
+ a_procset = pdfreference(pdfimmediateobject(tostring(a_procset)))
+ end
+ if dict then
+ if not d_procset then
+ d_procset = pdfdictionary {
+ ProcSet = a_procset
+ }
+ d_procset = pdfreference(pdfimmediateobject(tostring(d_procset)))
+ end
+ return d_procset
+ else
+ return a_procset
+ end
+ end
+
+end
+
+-- a left-over
+
+if environment.arguments.nocompression then
+ lpdf.setcompression(0,0,true)
+end
+
+
diff --git a/tex/context/base/mkiv/lpdf-mis.lua b/tex/context/base/mkiv/lpdf-mis.lua
index 6d1b09ca0..77f11918b 100644
--- a/tex/context/base/mkiv/lpdf-mis.lua
+++ b/tex/context/base/mkiv/lpdf-mis.lua
@@ -18,7 +18,6 @@ if not modules then modules = { } end modules ['lpdf-mis'] = {
local next, tostring, type = next, tostring, type
local format, gsub, formatters = string.format, string.gsub, string.formatters
local flattened = table.flattened
-local texset, texget = tex.set, tex.get
local backends, lpdf, nodes = backends, lpdf, nodes
@@ -30,7 +29,7 @@ local nuts = nodes.nuts
local copy_node = nuts.copy
local nodepool = nuts.pool
-local pdfpageliteral = nodepool.pdfpageliteral
+local pageliteral = nodepool.pageliteral
local register = nodepool.register
local pdfdictionary = lpdf.dictionary
@@ -54,6 +53,8 @@ local addtonames = lpdf.addtonames
local pdfgetmetadata = lpdf.getmetadata
+local texset = tex.set
+
local variables = interfaces.variables
local v_stop = variables.stop
@@ -72,11 +73,18 @@ local v_page = variables.page
local v_paper = variables.paper
local v_attachment = variables.attachment
local v_layer = variables.layer
+local v_lefttoright = variables.lefttoright
+local v_righttoleft = variables.righttoleft
+local v_title = variables.title
+
+local positive = register(pageliteral("/GSpositive gs"))
+local negative = register(pageliteral("/GSnegative gs"))
+local overprint = register(pageliteral("/GSoverprint gs"))
+local knockout = register(pageliteral("/GSknockout gs"))
+
+local omitextraboxes = false
-local positive = register(pdfpageliteral("/GSpositive gs"))
-local negative = register(pdfpageliteral("/GSnegative gs"))
-local overprint = register(pdfpageliteral("/GSoverprint gs"))
-local knockout = register(pdfpageliteral("/GSknockout gs"))
+directives.register("backend.omitextraboxes", function(v) omitextraboxes = v end)
local function initializenegative()
local a = pdfarray { 0, 1 }
@@ -86,7 +94,7 @@ local function initializenegative()
Range = a,
Domain = a,
}
- local negative = pdfdictionary { Type = g, TR = pdfreference(pdfflushstreamobject("{ 1 exch sub }",d)) }
+ local negative = pdfdictionary { Type = g, TR = pdfreference(pdfflushstreamobject("{ 1 exch sub }",d)) } -- can be shared
local positive = pdfdictionary { Type = g, TR = pdfconstant("Identity") }
adddocumentextgstate("GSnegative", pdfreference(pdfflushobject(negative)))
adddocumentextgstate("GSpositive", pdfreference(pdfflushobject(positive)))
@@ -230,6 +238,12 @@ local function setupidentity()
addtoinfo("ID", pdfstring(id), id) -- needed for pdf/x
--
addtoinfo("ConTeXt.Version",version)
+ --
+ local lmtx = codeinjections.lmtxmode()
+ if lmtx then
+ addtoinfo("ConTeXt.LMTX",formatters["%0.2f"](lmtx))
+ end
+ --
addtoinfo("ConTeXt.Time",os.date("%Y-%m-%d %H:%M"))
addtoinfo("ConTeXt.Jobname",jobname)
addtoinfo("ConTeXt.Url","www.pragma-ade.com")
@@ -254,7 +268,9 @@ local function flushjavascripts()
local a = pdfarray()
local pdf_javascript = pdfconstant("JavaScript")
for i=1,#t do
- local name, script = t[i][1], t[i][2]
+ local ti = t[i]
+ local name = ti[1]
+ local script = ti[2]
local j = pdfdictionary {
S = pdf_javascript,
JS = pdfreference(pdfflushstreamobject(script)),
@@ -304,14 +320,26 @@ local plusspecs = {
[v_paper] = {
paper = true,
},
+ [v_title] ={
+ title = true,
+ },
+ [v_lefttoright] ={
+ direction = "L2R",
+ },
+ [v_righttoleft] ={
+ direction = "R2R",
+ },
}
local pagespecs = {
--
- [v_max] = plusspecs[v_max],
- [v_bookmark] = plusspecs[v_bookmark],
- [v_attachment] = plusspecs[v_attachment],
- [v_layer] = plusspecs[v_layer],
+ [v_max] = plusspecs[v_max],
+ [v_bookmark] = plusspecs[v_bookmark],
+ [v_attachment] = plusspecs[v_attachment],
+ [v_layer] = plusspecs[v_layer],
+ [v_lefttoright] = plusspecs[v_lefttoright],
+ [v_righttoleft] = plusspecs[v_righttoleft],
+ [v_title] = plusspecs[v_title],
--
[v_none] = {
},
@@ -372,21 +400,23 @@ local cropoffset, bleedoffset, trimoffset, artoffset = 0, 0, 0, 0
local marked = false
local copies = false
+local getpagedimensions getpagedimensions = function()
+ getpagedimensions = backends.codeinjections.getpagedimensions
+ return getpagedimensions()
+end
+
function codeinjections.setupcanvas(specification)
local paperheight = specification.paperheight
local paperwidth = specification.paperwidth
local paperdouble = specification.doublesided
- if paperheight then
- texset('global','pageheight',paperheight)
- end
- if paperwidth then
- texset('global','pagewidth',paperwidth)
- end
+ --
+ paperwidth, paperheight = codeinjections.setpagedimensions(paperwidth,paperheight)
+ --
pagespec = specification.mode or pagespec
topoffset = specification.topoffset or 0
leftoffset = specification.leftoffset or 0
- height = specification.height or texget("pageheight")
- width = specification.width or texget("pagewidth")
+ height = specification.height or paperheight
+ width = specification.width or paperwidth
marked = specification.print
--
copies = specification.copies
@@ -433,13 +463,15 @@ local function documentspecification()
end
end
end
- --
- local layout = spec.layout
- local mode = spec.mode
- local fit = spec.fit
- local fixed = spec.fixed
- local duplex = spec.duplex
- local paper = spec.paper
+ -- maybe interfaces.variables
+ local layout = spec.layout
+ local mode = spec.mode
+ local fit = spec.fit
+ local fixed = spec.fixed
+ local duplex = spec.duplex
+ local paper = spec.paper
+ local title = spec.title
+ local direction = spec.direction
if layout then
addtocatalog("PageLayout",pdfconstant(layout))
end
@@ -458,34 +490,42 @@ local function documentspecification()
prints = pdfarray(flattened(pages.toranges(marked)))
end
end
- if fit or fixed or duplex or copies or paper or prints then
+ if fit or fixed or duplex or copies or paper or prints or title or direction then
addtocatalog("ViewerPreferences",pdfdictionary {
- FitWindow = fit and true or nil,
- PrintScaling = fixed and pdfconstant("None") or nil,
- Duplex = duplex and pdfconstant(duplex) or nil,
- NumCopies = copies and copies or nil,
- PickTrayByPDFSize = paper and true or nil,
- PrintPageRange = prints or nil,
+ FitWindow = fit and true or nil,
+ PrintScaling = fixed and pdfconstant("None") or nil,
+ Duplex = duplex and pdfconstant(duplex) or nil,
+ NumCopies = copies and copies or nil,
+ PickTrayByPDFSize = paper and true or nil,
+ PrintPageRange = prints or nil,
+ DisplayDocTitle = title and true or nil,
+ Direction = direction and pdfconstant(direction) or nil,
})
end
addtoinfo ("Trapped", pdfconstant("False")) -- '/Trapped' in /Info, 'Trapped' in XMP
addtocatalog("Version", pdfconstant(format("1.%s",pdfminorversion())))
+ addtocatalog("Lang", pdfstring(tokens.getters.macro("currentmainlanguage")))
end
-- temp hack: the mediabox is not under our control and has a precision of 5 digits
local factor = number.dimenfactors.bp
-local f_value = formatters["%0.6F"]
+local f_value = formatters["%.6F"]
+
+directives.register("pdf.stripzeros",function()
+ local f_value = formatters["%.6N"]
+end)
local function boxvalue(n) -- we could share them
return pdfverbose(f_value(factor * n))
end
local function pagespecification()
+ local paperwidth, paperheight = codeinjections.getpagedimensions()
local llx = leftoffset
- local lly = texget("pageheight") + topoffset - height
+ local lly = paperheight + topoffset - height
local urx = width - leftoffset
- local ury = texget("pageheight") - topoffset
+ local ury = paperheight - topoffset
-- boxes can be cached
local function extrabox(WhatBox,offset,always)
if offset ~= 0 or always then
@@ -497,10 +537,14 @@ local function pagespecification()
})
end
end
- extrabox("CropBox",cropoffset,true) -- mandate for rendering
- extrabox("TrimBox",trimoffset,true) -- mandate for pdf/x
- extrabox("BleedBox",bleedoffset) -- optional
- -- extrabox("ArtBox",artoffset) -- optional .. unclear what this is meant to do
+ if omitextraboxes then
+ -- only useful for testing / comparing
+ else
+ extrabox("CropBox",cropoffset,true) -- mandate for rendering
+ extrabox("TrimBox",trimoffset,true) -- mandate for pdf/x
+ extrabox("BleedBox",bleedoffset) -- optional
+ -- extrabox("ArtBox",artoffset) -- optional .. unclear what this is meant to do
+ end
end
lpdf.registerpagefinalizer(pagespecification,"page specification")
diff --git a/tex/context/base/mkiv/lpdf-nod.lua b/tex/context/base/mkiv/lpdf-nod.lua
index e3c1778f2..8bcf18c62 100644
--- a/tex/context/base/mkiv/lpdf-nod.lua
+++ b/tex/context/base/mkiv/lpdf-nod.lua
@@ -6,178 +6,84 @@ if not modules then modules = { } end modules ['lpdf-nod'] = {
license = "see context related readme files"
}
-local type = type
-
-local formatters = string.formatters
+if CONTEXTLMTXMODE > 1 then
+ return
+end
-local whatsitcodes = nodes.whatsitcodes
-local nodeinjections = backends.nodeinjections
+local nodecodes = nodes.nodecodes
+local whatsitcodes = nodes.whatsitcodes
-local nuts = nodes.nuts
-local tonut = nuts.tonut
+local nodeinjections = backends.nodeinjections
-local setfield = nuts.setfield
+local nuts = nodes.nuts
-local copy_node = nuts.copy
-local new_node = nuts.new
+local setfield = nuts.setfield
+local setdata = nuts.setdata
-local nodepool = nuts.pool
-local register = nodepool.register
+local copy_node = nuts.copy
+local new_node = nuts.new
-local literalvalues = nodes.literalvalues
+local nodepool = nuts.pool
+local register = nodepool.register
-local pdforiginliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdforiginliteral,"mode",literalvalues.origin)
-local pdfpageliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdfpageliteral, "mode",literalvalues.page)
-local pdfdirectliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdfdirectliteral,"mode",literalvalues.direct)
-local pdfrawliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdfrawliteral, "mode",literalvalues.raw)
+local whatsit_code = nodecodes.whatsit
-local pdfsave = register(new_node("whatsit", whatsitcodes.pdfsave))
-local pdfrestore = register(new_node("whatsit", whatsitcodes.pdfrestore))
-local pdfsetmatrix = register(new_node("whatsit", whatsitcodes.pdfsetmatrix))
------ pdfdest = register(new_node("whatsit", whatsitcodes.pdfdest)) setfield(pdfdest,"named_id",1) -- xyz_zoom untouched
------ pdfannot = register(new_node("whatsit", whatsitcodes.pdfannot))
+local savewhatsit_code = whatsitcodes.save
+local restorewhatsit_code = whatsitcodes.restore
+local setmatrixwhatsit_code = whatsitcodes.setmatrix
+local literalwhatsit_code = whatsitcodes.literal
-local variables = interfaces.variables
+local literalvalues = nodes.literalvalues
+local originliteral_code = literalvalues.origin
+local pageliteral_code = literalvalues.page
+local directliteral_code = literalvalues.direct
+local rawliteral_code = literalvalues.raw
-function nodepool.pdforiginliteral(str) local t = copy_node(pdforiginliteral) setfield(t,"data",str) return t end
-function nodepool.pdfpageliteral (str) local t = copy_node(pdfpageliteral ) setfield(t,"data",str) return t end
-function nodepool.pdfdirectliteral(str) local t = copy_node(pdfdirectliteral) setfield(t,"data",str) return t end
-function nodepool.pdfrawliteral (str) local t = copy_node(pdfrawliteral ) setfield(t,"data",str) return t end
+local tomatrix = drivers.helpers.tomatrix
-nodepool.pdfliteral = nodepool.pdfpageliteral -- best is to use a specific one: origin | page | direct | raw
+local originliteralnode = register(new_node(whatsit_code, literalwhatsit_code)) setfield(originliteralnode,"mode",originliteral_code)
+local pageliteralnode = register(new_node(whatsit_code, literalwhatsit_code)) setfield(pageliteralnode, "mode",pageliteral_code)
+local directliteralnode = register(new_node(whatsit_code, literalwhatsit_code)) setfield(directliteralnode,"mode",directliteral_code)
+local rawliteralnode = register(new_node(whatsit_code, literalwhatsit_code)) setfield(rawliteralnode, "mode",rawliteral_code)
-function nodepool.pdfsave()
- return copy_node(pdfsave)
-end
+function nodepool.originliteral(str) local t = copy_node(originliteralnode) setdata(t,str) return t end
+function nodepool.pageliteral (str) local t = copy_node(pageliteralnode ) setdata(t,str) return t end
+function nodepool.directliteral(str) local t = copy_node(directliteralnode) setdata(t,str) return t end
+function nodepool.rawliteral (str) local t = copy_node(rawliteralnode ) setdata(t,str) return t end
-function nodepool.pdfrestore()
- return copy_node(pdfrestore)
-end
+local literals = {
+ [originliteral_code] = originliteralnode, [literalvalues[originliteral_code]] = originliteralnode,
+ [pageliteral_code] = pageliteralnode, [literalvalues[pageliteral_code]] = pageliteralnode,
+ [directliteral_code] = directliteralnode, [literalvalues[directliteral_code]] = directliteralnode,
+ [rawliteral_code] = rawliteralnode, [literalvalues[rawliteral_code]] = rawliteralnode,
+}
-function nodepool.pdfsetmatrix(rx,sx,sy,ry,tx,ty) -- todo: tx ty
- local t = copy_node(pdfsetmatrix)
- if type(rx) == "string" then
- setfield(t,"data",rx)
+function nodepool.literal(mode,str)
+ if str then
+ local t = copy_node(literals[mode] or pageliteralnode)
+ setdata(t,str)
+ return t
else
- if not rx then
- rx = 1
- elseif rx == 0 then
- rx = 0.0001
- end
- if not ry then
- ry = 1
- elseif ry == 0 then
- ry = 0.0001
- end
- if not sx then
- sx = 0
- end
- if not sy then
- sy = 0
- end
- if sx == 0 and sy == 0 then
- if rx == 1 and ry == 1 then
- setfield(t,"data","1 0 0 1")
- else
- setfield(t,"data",formatters["%0.6F 0 0 %0.6F"](rx,ry))
- end
- else
- setfield(t,"data",formatters["%0.6F %0.6F %0.6F %0.6F"](rx,sx,sy,ry))
- end
+ local t = copy_node(pageliteralnode)
+ setdata(t,mode)
+ return t
end
- return t
end
-nodeinjections.save = nodepool.pdfsave
-nodeinjections.restore = nodepool.pdfrestore
-nodeinjections.transform = nodepool.pdfsetmatrix
-
--- the next one is implemented differently, using latelua
-
-function nodepool.pdfannotation(w,h,d,data,n)
- report("don't use node based annotations!")
- os.exit()
- -- local t = copy_node(pdfannot)
- -- if w and w ~= 0 then
- -- setfield(t,"width",w)
- -- end
- -- if h and h ~= 0 then
- -- setfield(t,"height",h)
- -- end
- -- if d and d ~= 0 then
- -- setfield(t,"depth",d)
- -- end
- -- if n then
- -- setfield(t,"objnum",n)
- -- end
- -- if data and data ~= "" then
- -- setfield(t,"data",data)
- -- end
- -- return t
+local savenode = register(new_node(whatsit_code, savewhatsit_code))
+local restorenode = register(new_node(whatsit_code, restorewhatsit_code))
+local setmatrixnode = register(new_node(whatsit_code, setmatrixwhatsit_code))
+
+function nodepool.save()
+ return copy_node(savenode)
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.
-
--- local views = { -- beware, we do support the pdf keys but this is *not* official
--- xyz = 0, [variables.standard] = 0,
--- fit = 1, [variables.fit] = 1,
--- fith = 2, [variables.width] = 2,
--- fitv = 3, [variables.height] = 3,
--- fitb = 4,
--- fitbh = 5, [variables.minwidth] = 5,
--- fitbv = 6, [variables.minheight] = 6,
--- fitr = 7,
--- }
-
-function nodepool.pdfdestination(w,h,d,name,view,n)
- report("don't use node based destinations!")
- os.exit()
- -- local t = copy_node(pdfdest)
- -- local hasdimensions = false
- -- if w and w ~= 0 then
- -- setfield(t,"width",w)
- -- hasdimensions = true
- -- end
- -- if h and h ~= 0 then
- -- setfield(t,"height",h)
- -- hasdimensions = true
- -- end
- -- if d and d ~= 0 then
- -- setfield(t,"depth",d)
- -- hasdimensions = true
- -- end
- -- if n then
- -- setfield(t,"objnum",n)
- -- end
- -- view = views[view] or view or 1 -- fit is default
- -- setfield(t,"dest_id",name)
- -- setfield(t,"dest_type",view)
- -- if hasdimensions and view == 0 then -- xyz
- -- -- see (!) s -> m -> t -> r
- -- -- linked
- -- local s = copy_node(pdfsave)
- -- local m = copy_node(pdfsetmatrix)
- -- local r = copy_node(pdfrestore)
- -- setfield(m,"data","1 0 0 1")
- -- setfield(s,"next",m)
- -- setfield(m,"next",t)
- -- setfield(t,"next",r)
- -- setfield(m,"prev",s)
- -- setfield(t,"prev",m)
- -- setfield(r,"prev",t)
- -- return s -- a list
- -- else
- -- return t
- -- end
+function nodepool.restore()
+ return copy_node(restorenode)
+end
+
+function nodepool.setmatrix(rx,sx,sy,ry,tx,ty)
+ local t = copy_node(setmatrixnode)
+ setdata(t,tomatrix(rx,sx,sy,ry,tx,ty))
+ return t
end
diff --git a/tex/context/base/mkiv/lpdf-pda.xml b/tex/context/base/mkiv/lpdf-pda.xml
index efdfc4d7d..2f07fed2d 100644
--- a/tex/context/base/mkiv/lpdf-pda.xml
+++ b/tex/context/base/mkiv/lpdf-pda.xml
@@ -30,6 +30,7 @@
<pdfx:ConTeXt.Url/>
<pdfx:ConTeXt.Support/>
<pdfx:ConTeXt.Version/>
+ <pdfx:ConTeXt.LMTX/>
<pdfx:TeX.Support/>
<pdfx:LuaTeX.Version/>
<pdfx:LuaTeX.Functionality/>
@@ -100,40 +101,76 @@
<pdfaSchema:property>
<rdf:Seq>
<rdf:li rdf:parseType="Resource">
- <pdfaProperty:category>external</pdfaProperty:category>
- <pdfaProperty:description>Name of the ConTeXt job</pdfaProperty:description>
- <pdfaProperty:name>ConTeXt.Jobname</pdfaProperty:name>
- <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Name of the ConTeXt job</pdfaProperty:description>
+ <pdfaProperty:name>ConTeXt.Jobname</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
</rdf:li>
<rdf:li rdf:parseType="Resource">
- <pdfaProperty:category>external</pdfaProperty:category>
- <pdfaProperty:description>Time stamp of ConTeXt version</pdfaProperty:description>
- <pdfaProperty:name>ConTeXt.Time</pdfaProperty:name>
- <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Time stamp of ConTeXt version</pdfaProperty:description>
+ <pdfaProperty:name>ConTeXt.Time</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
</rdf:li>
<rdf:li rdf:parseType="Resource">
- <pdfaProperty:category>external</pdfaProperty:category>
- <pdfaProperty:description>ConTeXt website</pdfaProperty:description>
- <pdfaProperty:name>ConTeXt.Url</pdfaProperty:name>
- <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>ConTeXt website</pdfaProperty:description>
+ <pdfaProperty:name>ConTeXt.Url</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
</rdf:li>
<rdf:li rdf:parseType="Resource">
- <pdfaProperty:category>external</pdfaProperty:category>
- <pdfaProperty:description>ConTeXt version</pdfaProperty:description>
- <pdfaProperty:name>ConTeXt.Version</pdfaProperty:name>
- <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>ConTeXt support</pdfaProperty:description>
+ <pdfaProperty:name>ConTeXt.Support</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
</rdf:li>
<rdf:li rdf:parseType="Resource">
- <pdfaProperty:category>external</pdfaProperty:category>
- <pdfaProperty:description>Banner of pdftex or one of its successors</pdfaProperty:description>
- <pdfaProperty:name>PTEX.Fullbanner</pdfaProperty:name>
- <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>ConTeXt version</pdfaProperty:description>
+ <pdfaProperty:name>ConTeXt.Version</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
</rdf:li>
<rdf:li rdf:parseType="Resource">
- <pdfaProperty:category>external</pdfaProperty:category>
- <pdfaProperty:description>Document identifier</pdfaProperty:description>
- <pdfaProperty:name>ID</pdfaProperty:name>
- <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>ConTeXt LMTX version</pdfaProperty:description>
+ <pdfaProperty:name>ConTeXt.LMTX</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>TeX support</pdfaProperty:description>
+ <pdfaProperty:name>TeX.Support</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>LuaTeX version</pdfaProperty:description>
+ <pdfaProperty:name>LuaTeX.Version</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>LuaTeX functionality</pdfaProperty:description>
+ <pdfaProperty:name>LuaTeX.Functionality</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>LuaTeX Lua version</pdfaProperty:description>
+ <pdfaProperty:name>LuaTeX.LuaVersion</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>LuaTeX platform</pdfaProperty:description>
+ <pdfaProperty:name>LuaTeX.Platform</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Document identifier</pdfaProperty:description>
+ <pdfaProperty:name>ID</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
</rdf:li>
</rdf:Seq>
</pdfaSchema:property>
diff --git a/tex/context/base/mkiv/lpdf-pde.lua b/tex/context/base/mkiv/lpdf-pde.lua
new file mode 100644
index 000000000..9d14f8f5e
--- /dev/null
+++ b/tex/context/base/mkiv/lpdf-pde.lua
@@ -0,0 +1,1157 @@
+if not modules then modules = { } end modules ['lpdf-epd'] = {
+ version = 1.001,
+ comment = "companion to lpdf-epa.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ history = "this one replaces the poppler/pdfe binding",
+}
+
+-- \enabledirectives[graphics.pdf.uselua]
+-- \enabledirectives[graphics.pdf.recompress]
+-- \enabledirectives[graphics.pdf.stripmarked]
+
+-- maximum integer : +2^32
+-- maximum real : +2^15
+-- minimum real : 1/(2^16)
+
+-- get_flagged : does that still work
+
+-- ppdoc_permissions (ppdoc *pdf);
+
+-- PPSTRING_ENCODED 1 << 0
+-- PPSTRING_DECODED 1 << 1
+-- PPSTRING_EXEC 1 << 2 postscript only
+-- PPSTRING_PLAIN 0
+-- PPSTRING_BASE16 1 << 3
+-- PPSTRING_BASE85 1 << 4
+-- PPSTRING_UTF16BE 1 << 5
+-- PPSTRING_UTF16LE 1 << 6
+
+-- PPDOC_ALLOW_PRINT 1 << 2 printing
+-- PPDOC_ALLOW_MODIFY 1 << 3 filling form fields, signing, creating template pages
+-- PPDOC_ALLOW_COPY 1 << 4 copying, copying for accessibility
+-- PPDOC_ALLOW_ANNOTS 1 << 5 filling form fields, copying, signing
+-- PPDOC_ALLOW_EXTRACT 1 << 9 contents copying for accessibility
+-- PPDOC_ALLOW_ASSEMBLY 1 << 10 no effect
+-- PPDOC_ALLOW_PRINT_HIRES 1 << 11 no effect
+
+-- PPCRYPT_NONE 0 no encryption, go ahead
+-- PPCRYPT_DONE 1 encryption present but password succeeded, go ahead
+-- PPCRYPT_PASS -1 encryption present, need non-empty password
+-- PPCRYPT_FAIL -2 invalid or unsupported encryption (eg. undocumented in pdf spec)
+
+local setmetatable, rawset, rawget, type, next = setmetatable, rawset, rawget, type, next
+local tostring, tonumber, unpack = tostring, tonumber, unpack
+local char, byte, find = string.char, string.byte, string.find
+local abs = math.abs
+local concat, swapped, sortedhash, sortedkeys = table.concat, table.swapped, table.sortedhash, table.sortedkeys
+local utfchar = string.char
+local setmetatableindex = table.setmetatableindex
+
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local P, C, S, R, Ct, Cc, V, Carg, Cs, Cf, Cg = lpeg.P, lpeg.C, lpeg.S, lpeg.R, lpeg.Ct, lpeg.Cc, lpeg.V, lpeg.Carg, lpeg.Cs, lpeg.Cf, lpeg.Cg
+
+if not lpdf then
+ require("lpdf-aux")
+end
+
+if not (number and number.dimenfactors) then
+ require("util-dim")
+end
+
+local epdf = pdfe
+ lpdf = lpdf or { }
+local lpdf = lpdf
+local lpdf_epdf = { }
+lpdf.epdf = lpdf_epdf
+
+local openPDF = epdf.open
+local newPDF = epdf.new
+local closePDF = epdf.close
+
+local getcatalog = epdf.getcatalog
+local getinfo = epdf.getinfo
+local gettrailer = epdf.gettrailer
+local getnofpages = epdf.getnofpages
+local getversion = epdf.getversion
+local getbox = epdf.getbox
+local getstatus = epdf.getstatus
+local unencrypt = epdf.unencrypt
+
+local dictionarytotable = epdf.dictionarytotable
+local arraytotable = epdf.arraytotable
+local pagestotable = epdf.pagestotable
+local readwholestream = epdf.readwholestream
+
+local getfromreference = pdfe.getfromreference
+
+local report_epdf = logs.reporter("epdf")
+
+local allocate = utilities.storage.allocate
+
+local bpfactor = number.dimenfactors.bp
+
+local objectcodes = { [0] =
+ "none",
+ "null",
+ "bool",
+ "integer",
+ "number",
+ "name",
+ "string",
+ "array",
+ "dictionary",
+ "stream",
+ "reference",
+}
+
+local encryptioncodes = {
+ [0] = "notencrypted",
+ [1] = "unencrypted",
+ [-1] = "protected",
+ [-2] = "failure",
+}
+
+objectcodes = allocate(swapped(objectcodes,objectcodes))
+encryptioncodes = allocate(swapped(encryptioncodes,encryptioncodes))
+
+pdfe.objectcodes = objectcodes
+pdfe.encryptioncodes = encryptioncodes
+
+local null_object_code = objectcodes.null
+local reference_object_code = objectcodes.reference
+
+local none_object_code = objectcodes.none
+local null_object_code = objectcodes.null
+local bool_object_code = objectcodes.bool
+local integer_object_code = objectcodes.integer
+local number_object_code = objectcodes.number
+local name_object_code = objectcodes.name
+local string_object_code = objectcodes.string
+local array_object_code = objectcodes.array
+local dictionary_object_code = objectcodes.dictionary
+local stream_object_code = objectcodes.stream
+local reference_object_code = objectcodes.reference
+
+local checked_access
+local get_flagged -- from pdfe -> lpdf
+
+if lpdf.dictionary then
+
+ -- we're in context
+
+ local pdfdictionary = lpdf.dictionary
+ local pdfarray = lpdf.array
+ local pdfconstant = lpdf.constant
+ local pdfstring = lpdf.string
+ local pdfunicode = lpdf.unicode
+
+ get_flagged = function(t,f,k)
+ local tk = t[k] -- triggers resolve
+ local fk = f[k]
+ if not fk then
+ return tk
+ elseif fk == "name" then
+ return pdfconstant(tk)
+ elseif fk == "array" then
+ return pdfarray(tk)
+ elseif fk == "dictionary" then
+ return pdfarray(tk)
+ elseif fk == "rawtext" then
+ return pdfstring(tk)
+ elseif fk == "unicode" then
+ return pdfunicode(tk)
+ else
+ return tk
+ end
+ end
+
+else
+
+ get_flagged = function(t,f,k)
+ return t[k]
+ end
+
+end
+
+-- We need to convert the string from utf16 although there is no way to
+-- check if we have a regular string starting with a bom. So, we have
+-- na dilemma here: a pdf doc encoded string can be invalid utf.
+
+-- <hex encoded> : implicit 0 appended if odd
+-- (byte encoded) : \( \) \\ escaped
+--
+-- <FE><FF> : utf16be
+--
+-- \r \r \t \b \f \( \) \\ \NNN and \<newline> : append next line
+--
+-- the getString function gives back bytes so we don't need to worry about
+-- the hex aspect.
+
+local some_dictionary
+local some_array
+local some_stream
+local some_reference
+
+local some_string = lpdf.frombytes
+
+local function get_value(document,t,key)
+ if not key then
+ return
+ end
+ local value = t[key]
+ if not value then
+ return
+ end
+ if type(value) ~= "table" then
+ return value
+ end
+ -- we can assume names to be simple and strings to be tables
+ local kind = value[1]
+ if kind == name_object_code then
+ return value[2]
+ elseif kind == string_object_code then
+ return some_string(value[2],value[3])
+ elseif kind == array_object_code then
+ return some_array(value[2],document)
+ elseif kind == dictionary_object_code then
+ return some_dictionary(value[2],document)
+ elseif kind == stream_object_code then
+ return some_stream(value,document)
+ elseif kind == reference_object_code then
+ return some_reference(value,document)
+ end
+ return value
+end
+
+some_dictionary = function (d,document)
+ local f = dictionarytotable(d,true)
+ local t = setmetatable({ __raw__ = f, __type__ = dictionary_object_code }, {
+ __index = function(t,k)
+ return get_value(document,f,k)
+ end,
+ __call = function(t,k)
+ return get_flagged(t,f,k)
+ end,
+ } )
+ return t, "dictionary"
+end
+
+some_array = function (a,document)
+ local f = arraytotable(a,true)
+ local n = #f
+ local t = setmetatable({ __raw__ = f, __type__ = array_object_code, n = n }, {
+ __index = function(t,k)
+ return get_value(document,f,k)
+ end,
+ __call = function(t,k)
+ return get_flagged(t,f,k)
+ end,
+ __len = function(t,k)
+ return n
+ end,
+ } )
+ return t, "array"
+end
+
+some_stream = function(s,d,document)
+ local f = dictionarytotable(d,true)
+ local t = setmetatable({ __raw__ = f, __type__ = stream_object_code }, {
+ __index = function(t,k)
+ return get_value(document,f,k)
+ end,
+ __call = function(t,raw)
+ if raw == false then
+ return readwholestream(s,false) -- original
+ else
+ return readwholestream(s,true) -- uncompressed
+ end
+ end,
+ } )
+ return t, "stream"
+end
+
+some_reference = function(r,document)
+ local objnum = r[3]
+ local cached = document.__cache__[objnum]
+ if not cached then
+ local kind, object, b, c = getfromreference(r[2])
+ if kind == dictionary_object_code then
+ cached = some_dictionary(object,document)
+ elseif kind == array_object_code then
+ cached = some_array(object,document)
+ elseif kind == stream_object_code then
+ cached = some_stream(object,b,document)
+ else
+ cached = { kind, object, b, c }
+ -- really cache this?
+ end
+ document.__cache__[objnum] = cached
+ document.__xrefs__[cached] = objnum
+ end
+ return cached
+end
+
+local resolvers = { }
+lpdf_epdf.resolvers = resolvers
+
+local function resolve(document,k)
+ local resolver = resolvers[k]
+ if resolver then
+ local entry = resolver(document)
+ document[k] = entry
+ return entry
+ end
+end
+
+local function getnames(document,n,target) -- direct
+ if n then
+ local Names = n.Names
+ if Names then
+ if not target then
+ target = { }
+ end
+ for i=1,#Names,2 do
+ target[Names[i]] = Names[i+1]
+ end
+ else
+ local Kids = n.Kids
+ if Kids then
+ for i=1,#Kids do
+ target = getnames(document,Kids[i],target)
+ end
+ end
+ end
+ return target
+ end
+end
+
+local function getkids(document,n,target) -- direct
+ if n then
+ local Kids = n.Kids
+ if Kids then
+ for i=1,#Kids do
+ target = getkids(document,Kids[i],target)
+ end
+ elseif target then
+ target[#target+1] = n
+ else
+ target = { n }
+ end
+ return target
+ end
+end
+
+function resolvers.destinations(document)
+ local Names = document.Catalog.Names
+ return getnames(document,Names and Names.Dests)
+end
+
+function resolvers.javascripts(document)
+ local Names = document.Catalog.Names
+ return getnames(document,Names and Names.JavaScript)
+end
+
+function resolvers.widgets(document)
+ local Names = document.Catalog.AcroForm
+ return Names and Names.Fields
+end
+
+function resolvers.embeddedfiles(document)
+ local Names = document.Catalog.Names
+ return getnames(document,Names and Names.EmbeddedFiles)
+end
+
+-- /OCProperties <<
+-- /OCGs [ 15 0 R 17 0 R 19 0 R 21 0 R 23 0 R 25 0 R 27 0 R ]
+-- /D <<
+-- /Order [ 15 0 R 17 0 R 19 0 R 21 0 R 23 0 R 25 0 R 27 0 R ]
+-- /ON [ 15 0 R 17 0 R 19 0 R 21 0 R 23 0 R 25 0 R 27 0 R ]
+-- /OFF [ ]
+-- >>
+-- >>
+
+function resolvers.layers(document)
+ local properties = document.Catalog.OCProperties
+ if properties then
+ local layers = properties.OCGs
+ if layers then
+ local t = { }
+ for i=1,#layers do
+ local layer = layers[i]
+ t[i] = layer.Name
+ end
+ -- t.n = n
+ return t
+ end
+ end
+end
+
+function resolvers.structure(document)
+ -- this might become a tree
+ return document.Catalog.StructTreeRoot
+end
+
+function resolvers.pages(document)
+ local __data__ = document.__data__
+ local __xrefs__ = document.__xrefs__
+ local __cache__ = document.__cache__
+ --
+ local nofpages = document.nofpages
+ local pages = { }
+ local rawpages = pagestotable(__data__)
+ document.pages = pages
+ --
+ for pagenumber=1,nofpages do
+ local rawpagedata = rawpages[pagenumber]
+ local pagereference = rawpagedata[3]
+ local pageobject = rawpagedata[1]
+ local pagedata = some_dictionary(pageobject,document)
+ if pagedata and pageobject then
+ pagedata.number = pagenumber
+ pagedata.MediaBox = getbox(pageobject,"MediaBox")
+ pagedata.CropBox = getbox(pageobject,"CropBox")
+ pagedata.BleedBox = getbox(pageobject,"BleedBox")
+ pagedata.ArtBox = getbox(pageobject,"ArtBox")
+ pagedata.TrimBox = getbox(pageobject,"TrimBox")
+ pages[pagenumber] = pagedata
+ __xrefs__[pagedata] = pagereference
+ __cache__[pagereference] = pagedata
+ else
+ report_epdf("missing pagedata for page %i",i)
+ end
+ end
+ --
+ -- pages.n = nofpages
+ --
+ return pages
+end
+
+local loaded = { }
+local nofloaded = 0
+
+function lpdf_epdf.load(filename,userpassword,ownerpassword,fromstring)
+ local document = loaded[filename]
+ if not document then
+ statistics.starttiming(lpdf_epdf)
+ local __data__
+ if fromstring then
+ __data__ = newPDF(filename,#filename)
+ else
+ __data__ = openPDF(filename)
+ end
+ if __data__ then
+ if userpassword and getstatus(__data__) < 0 then
+ unencrypt(__data__,userpassword,nil)
+ end
+ if ownerpassword and getstatus(__data__) < 0 then
+ unencrypt(__data__,nil,ownerpassword)
+ end
+ if getstatus(__data__) < 0 then
+ report_epdf("the document is encrypted, provide proper passwords",getstatus(__data__))
+ __data__ = false
+ end
+ if __data__ then
+ document = {
+ filename = filename,
+ __cache__ = { },
+ __xrefs__ = { },
+ __fonts__ = { },
+ __copied__ = { },
+ __data__ = __data__,
+ }
+ document.Catalog = some_dictionary(getcatalog(__data__),document)
+ document.Info = some_dictionary(getinfo(__data__),document)
+ document.Trailer = some_dictionary(gettrailer(__data__),document)
+ --
+ setmetatableindex(document,resolve)
+ --
+ document.majorversion, document.minorversion = getversion(__data__)
+ --
+ document.nofpages = getnofpages(__data__)
+ else
+ document = false
+ end
+ else
+ document = false
+ end
+ loaded[filename] = document
+ loaded[document] = document
+ statistics.stoptiming(lpdf_epdf)
+ -- print(statistics.elapsedtime(lpdf_epdf))
+ end
+ return document or nil
+end
+
+function lpdf_epdf.unload(filename)
+ if type(filename) == "table" then
+ filename = filename.filename
+ end
+ if type(filename) == "string" then
+ local document = loaded[filename]
+ if document then
+-- report_epdf("%04i closed: %s",nofloaded,filename)
+-- nofloaded = nofloaded - 1
+ loaded[document] = nil
+ loaded[filename] = nil
+ end
+ end
+end
+
+-- for k, v in expanded(t) do
+
+local function expanded(t)
+ local function iterator(raw,k)
+ local k, v = next(raw,k)
+ if v then
+ return k, t[k]
+ end
+ end
+ return iterator, t.__raw__, nil
+end
+
+---------.expand = expand
+lpdf_epdf.expanded = expanded
+
+-- we could resolve the text stream in one pass if we directly handle the
+-- font but why should we complicate things
+
+local spaces = lpegpatterns.whitespace^1
+local optspaces = lpegpatterns.whitespace^0
+local numchar = P("\\")/"" * (R("09")^3/function(s) return char(tonumber(s,8)) end)
+ + P("\\") * P(1)
+local key = P("/") * C(R("AZ","az","09","__")^1)
+local number = Ct(Cc("number") * (lpegpatterns.number/tonumber))
+local keyword = Ct(Cc("name") * key)
+local operator = C((R("AZ","az")+P("*")+P("'")+P('"'))^1)
+
+local grammar = P { "start",
+ start = (keyword + number + V("dictionary") + V("array") + V("hexstring") + V("decstring") + spaces)^1,
+ keyvalue = key * optspaces * V("start"),
+ array = Ct(Cc("array") * P("[") * Ct(V("start")^1) * P("]")),
+ dictionary = Ct(Cc("dict") * P("<<") * Ct(V("keyvalue")^1) * P(">>")),
+ hexstring = Ct(Cc("hex") * P("<") * Cs(( 1-P(">"))^1) * P(">")),
+ decstring = Ct(Cc("dec") * P("(") * Cs((numchar+1-(P")"))^1) * P(")")), -- untested
+}
+
+local operation = Ct(grammar^1 * operator)
+local parser = Ct((operation + P(1))^1)
+
+-- todo: speed this one up
+
+local numchar = P("\\") * (R("09")^3 + P(1))
+local number = lpegpatterns.number
+local keyword = P("/") * R("AZ","az","09","__")^1
+local operator = (R("AZ","az")+P("*")+P("'")+P('"'))^1
+
+local skipstart = P("BDC") + P("BMC") + P("DP") + P("MP")
+local skipstop = P("EMC")
+local skipkeep = P("/ActualText")
+
+local grammar = P { "skip",
+ start = keyword + number + V("dictionary") + V("array") + V("hexstring") + V("decstring") + spaces,
+ keyvalue = optspaces * (keyword * optspaces * V("start") * optspaces)^1,
+ xeyvalue = optspaces * ((keyword - skipkeep) * optspaces * V("start") * optspaces)^1,
+ array = P("[") * V("start")^0 * P("]"),
+ dictionary = P("<<") * V("keyvalue")^0 * P(">>"),
+ xictionary = P("<<") * V("xeyvalue")^0 * P(">>"),
+ hexstring = P("<") * ( 1-P(">"))^0 * P(">"),
+ decstring = P("(") * (numchar+1-(P")"))^0 * P(")"),
+ skip = (optspaces * ( keyword * optspaces * V("xictionary") * optspaces * skipstart + skipstop) / "")
+ + V("start")
+ + operator
+}
+
+local stripper = Cs((grammar + P(1))^1)
+
+function lpdf_epdf.parsecontent(str)
+ return lpegmatch(parser,str)
+end
+
+function lpdf_epdf.stripcontent(str)
+ if find(str,"EMC") then
+ return lpegmatch(stripper,str)
+ else
+ return str
+ end
+end
+
+-- beginbfrange : <start> <stop> <firstcode>
+-- <start> <stop> [ <firstsequence> <firstsequence> <firstsequence> ]
+-- beginbfchar : <code> <newcodes>
+
+local fromsixteen = lpdf.fromsixteen -- maybe inline the lpeg ... but not worth it
+
+local function f_bfchar(t,a,b)
+ t[tonumber(a,16)] = fromsixteen(b)
+end
+
+local function f_bfrange_1(t,a,b,c)
+ print("todo 1",a,b,c)
+ -- c is string
+ -- todo t[tonumber(a,16)] = fromsixteen(b)
+end
+
+local function f_bfrange_2(t,a,b,c)
+ print("todo 2",a,b,c)
+ -- c is table
+ -- todo t[tonumber(a,16)] = fromsixteen(b)
+end
+
+local optionals = spaces^0
+local hexstring = optionals * P("<") * C((1-P(">"))^1) * P(">")
+local bfchar = Carg(1) * hexstring * hexstring / f_bfchar
+local bfrange = Carg(1) * hexstring * hexstring * hexstring / f_bfrange_1
+ + Carg(1) * hexstring * hexstring * optionals * P("[") * Ct(hexstring^1) * optionals * P("]") / f_bfrange_2
+local fromunicode = (
+ P("beginbfchar" ) * bfchar ^1 * optionals * P("endbfchar" ) +
+ P("beginbfrange") * bfrange^1 * optionals * P("endbfrange") +
+ spaces +
+ P(1)
+)^1 * Carg(1)
+
+local function analyzefonts(document,resources) -- unfinished, see mtx-pdf for better code
+ local fonts = document.__fonts__
+ if resources then
+ local fontlist = resources.Font
+ if fontlist then
+ for id, data in expanded(fontlist) do
+ if not fonts[id] then
+ -- a quick hack ... I will look into it more detail if I find a real
+ -- -application for it
+ local tounicode = data.ToUnicode()
+ if tounicode then
+ tounicode = lpegmatch(fromunicode,tounicode,1,{})
+ end
+ fonts[id] = {
+ tounicode = type(tounicode) == "table" and tounicode or { }
+ }
+ setmetatableindex(fonts[id],"self")
+ end
+ end
+ end
+ end
+ return fonts
+end
+
+local more = 0
+local unic = nil -- cheaper than passing each time as Carg(1)
+
+local p_hex_to_utf = C(4) / function(s) -- needs checking !
+ local now = tonumber(s,16)
+ if more > 0 then
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
+ more = 0
+ return unic[now] or utfchar(now)
+ elseif now >= 0xD800 and now <= 0xDBFF then
+ more = now
+ -- return ""
+ else
+ return unic[now] or utfchar(now)
+ end
+end
+
+local p_dec_to_utf = C(1) / function(s) -- needs checking !
+ local now = byte(s)
+ return unic[now] or utfchar(now)
+end
+
+local p_hex_to_utf = P(true) / function() more = 0 end * Cs(p_hex_to_utf^1)
+local p_dec_to_utf = P(true) / function() more = 0 end * Cs(p_dec_to_utf^1)
+
+function lpdf_epdf.getpagecontent(document,pagenumber)
+
+ local page = document.pages[pagenumber]
+
+ if not page then
+ return
+ end
+
+ local fonts = analyzefonts(document,page.Resources)
+
+ local content = page.Contents() or ""
+ local list = lpegmatch(parser,content)
+ local font = nil
+ -- local unic = nil
+
+ for i=1,#list do
+ local entry = list[i]
+ local size = #entry
+ local operator = entry[size]
+ if operator == "Tf" then
+ font = fonts[entry[1]]
+ unic = font.tounicode
+ elseif operator == "TJ" then -- { array, TJ }
+ local list = entry[1]
+ for i=1,#list do
+ local li = list[i]
+ if type(li) == "table" then
+ if li[1] == "hex" then
+ list[i] = lpegmatch(p_hex_to_utf,li[2])
+ else
+ list[i] = lpegmatch(p_dec_to_utf,li[2])
+ end
+ else
+ -- kern
+ end
+ end
+ elseif operator == "Tj" or operator == "'" or operator == '"' then -- { string, Tj } { string, ' } { n, m, string, " }
+ local list = entry[size-1]
+ if list[1] == "hex" then
+ list[2] = lpegmatch(p_hex_to_utf,li[2])
+ else
+ list[2] = lpegmatch(p_dec_to_utf,li[2])
+ end
+ end
+ end
+
+ unic = nil -- can be collected
+
+ return list
+
+end
+
+-- This is also an experiment. When I really need it I can improve it, for instance
+-- with proper position calculating. It might be usefull for some search or so.
+
+local softhyphen = utfchar(0xAD) .. "$"
+local linefactor = 1.3
+
+function lpdf_epdf.contenttotext(document,list) -- maybe signal fonts
+ local last_y = 0
+ local last_f = 0
+ local text = { }
+ local last = 0
+
+ for i=1,#list do
+ local entry = list[i]
+ local size = #entry
+ local operator = entry[size]
+ if operator == "Tf" then
+ last_f = entry[2]
+ elseif operator == "TJ" then
+ local list = entry[1]
+ for i=1,#list do
+ local li = list[i]
+ if type(li) == "string" then
+ last = last + 1
+ text[last] = li
+ elseif li < -50 then
+ last = last + 1
+ text[last] = " "
+ end
+ end
+ line = concat(list)
+ elseif operator == "Tj" then
+ last = last + 1
+ text[last] = entry[size-1]
+ elseif operator == "cm" or operator == "Tm" then
+ local ty = entry[6]
+ local dy = abs(last_y - ty)
+ if dy > linefactor*last_f then
+ if last > 0 then
+ if find(text[last],softhyphen,1,true) then
+ -- ignore
+ else
+ last = last + 1
+ text[last] = "\n"
+ end
+ end
+ end
+ last_y = ty
+ end
+ end
+
+ return concat(text)
+end
+
+function lpdf_epdf.getstructure(document,list) -- just a test
+ local depth = 0
+ for i=1,#list do
+ local entry = list[i]
+ local size = #entry
+ local operator = entry[size]
+ if operator == "BDC" then
+ report_epdf("%w%s : %s",depth,entry[1] or "?",entry[2] and entry[2].MCID or "?")
+ depth = depth + 1
+ elseif operator == "EMC" then
+ depth = depth - 1
+ elseif operator == "TJ" then
+ local list = entry[1]
+ for i=1,#list do
+ local li = list[i]
+ if type(li) == "string" then
+ report_epdf("%w > %s",depth,li)
+ elseif li < -50 then
+ report_epdf("%w >",depth,li)
+ end
+ end
+ elseif operator == "Tj" then
+ report_epdf("%w > %s",depth,entry[size-1])
+ end
+ end
+end
+
+if img then do
+
+ -- This can be made a bit faster (just get raw data and pass it) but I will
+ -- do that later. In the end the benefit is probably neglectable.
+
+ local recompress = false
+ local stripmarked = false
+
+ local copydictionary = nil
+ local copyarray = nil
+
+ local pdfreserveobject = lpdf.reserveobject
+ local shareobjectreference = lpdf.shareobjectreference
+ local pdfflushobject = lpdf.flushobject
+ local pdfflushstreamobject = lpdf.flushstreamobject
+ local pdfreference = lpdf.reference
+ local pdfconstant = lpdf.constant
+ local pdfarray = lpdf.array
+ local pdfdictionary = lpdf.dictionary
+ local pdfnull = lpdf.null
+ local pdfliteral = lpdf.literal
+
+ local report = logs.reporter("backend","xobjects")
+
+ local factor = 65536 / (7200/7227) -- 1/number.dimenfactors.bp
+
+ local createimage = images.create
+
+ directives.register("graphics.pdf.recompress", function(v) recompress = v end)
+ directives.register("graphics.pdf.stripmarked", function(v) stripmarked = v end)
+
+ local function scaledbbox(b)
+ return { b[1]*factor, b[2]*factor, b[3]*factor, b[4]*factor }
+ end
+
+ local codecs = {
+ ASCIIHexDecode = true,
+ ASCII85Decode = true,
+ RunLengthDecode = true,
+ FlateDecode = true,
+ LZWDecode = true,
+ }
+
+ local function deepcopyobject(xref,copied,value)
+ -- no need for tables, just nested loop with obj
+ local objnum = xref[value]
+ if objnum then
+ local usednum = copied[objnum]
+ if usednum then
+ -- report("%s object %i is reused",kind,objnum)
+ else
+ usednum = pdfreserveobject()
+ copied[objnum] = usednum
+ local entry = value
+ local kind = entry.__type__
+ if kind == array_object_code then
+ local a = copyarray(xref,copied,entry)
+ pdfflushobject(usednum,tostring(a))
+ elseif kind == dictionary_object_code then
+ local d = copydictionary(xref,copied,entry)
+ pdfflushobject(usednum,tostring(d))
+ elseif kind == stream_object_code then
+ local d = copydictionary(xref,copied,entry)
+ local filter = d.Filter
+ if filter and codecs[filter] and recompress then
+ -- recompress
+ d.Filter = nil
+ d.Length = nil
+ d.DecodeParms = nil -- relates to filter
+ d.DL = nil -- needed?
+ local s = entry() -- get uncompressed stream
+ pdfflushstreamobject(s,d,true,usednum) -- compress stream
+ else
+ -- keep as-is, even Length which indicates the
+ -- decompressed length
+ local s = entry(false) -- get compressed stream
+ -- pdfflushstreamobject(s,d,false,usednum,true) -- don't compress stream
+ pdfflushstreamobject(s,d,"raw",usednum) -- don't compress stream
+ end
+ else
+ local t = type(value)
+ if t == "string" then
+ value = pdfconstant(value)
+ elseif t == "table" then
+ local kind = value[1]
+ local entry = value[2]
+ if kind == name_object_code then
+ value = pdfconstant(entry)
+ elseif kind == string_object_code then
+ value = pdfliteral(entry,value[3])
+ elseif kind == null_object_code then
+ value = pdfnull()
+ elseif kind == reference_object_code then
+ value = deepcopyobject(xref,copied,entry)
+ else
+ value = tostring(entry)
+ end
+ end
+ pdfflushobject(usednum,value)
+ end
+ end
+ return pdfreference(usednum)
+ elseif kind == stream_object_code then
+ report("stream not done: %s", objectcodes[kind] or "?")
+ else
+ report("object not done: %s", objectcodes[kind] or "?")
+ end
+ end
+
+ local function copyobject(xref,copied,object,key,value)
+ if not value then
+ value = object.__raw__[key]
+ end
+ local t = type(value)
+ if t == "string" then
+ return pdfconstant(value)
+ elseif t ~= "table" then
+ return value
+ end
+ local kind = value[1]
+ if kind == name_object_code then
+ return pdfconstant(value[2])
+ elseif kind == string_object_code then
+ return pdfliteral(value[2],value[3])
+ elseif kind == array_object_code then
+ return copyarray(xref,copied,object[key])
+ elseif kind == dictionary_object_code then
+ return copydictionary(xref,copied,object[key])
+ elseif kind == null_object_code then
+ return pdfnull()
+ elseif kind == reference_object_code then
+ -- expand
+ return deepcopyobject(xref,copied,object[key])
+ else
+ report("weird: %s", objecttypes[kind] or "?")
+ end
+ end
+
+ copyarray = function (xref,copied,object)
+ local target = pdfarray()
+ local source = object.__raw__
+ for i=1,#source do
+ target[i] = copyobject(xref,copied,object,i,source[i])
+ end
+ return target
+ end
+
+ local plugins = nil
+
+ -- Sorting the hash slows down upto 5% bit but it is still as fast as the C
+ -- code. We could loop over the index instead but sorting might be nicer in
+ -- the end.
+
+ copydictionary = function (xref,copied,object)
+ local target = pdfdictionary()
+ local source = object.__raw__
+ -- for key, value in next, source do
+ for key, value in sortedhash(source) do
+ if plugins then
+ local p = plugins[key]
+ if p then
+ target[key] = p(xref,copied,object,key,value,copyobject) -- maybe a table of methods
+ else
+ target[key] = copyobject(xref,copied,object,key,value)
+ end
+ else
+ target[key] = copyobject(xref,copied,object,key,value)
+ end
+ end
+ return target
+ end
+
+ -- local function copyresources(pdfdoc,xref,copied,pagedata)
+ -- local Resources = pagedata.Resources
+ -- if Resources then
+ -- local r = pdfreserveobject()
+ -- local d = copydictionary(xref,copied,Resources)
+ -- pdfflushobject(r,tostring(d))
+ -- return pdfreference(r)
+ -- end
+ -- end
+
+ local function copyresources(pdfdoc,xref,copied,pagedata)
+ local Resources = pagedata.Resources
+ --
+ -- -- This needs testing:
+ --
+ -- if not Resources then
+ -- local Parent = page.Parent
+ -- while (Parent and (Parent.__type__ == dictionary_object_code or Parent.__type__ == reference_object_code) do
+ -- Resources = Parent.Resources
+ -- if Resources then
+ -- break
+ -- end
+ -- Parent = Parent.Parent
+ -- end
+ -- end
+ if Resources then
+ local d = copydictionary(xref,copied,Resources)
+ return shareobjectreference(d)
+ end
+ end
+
+ local openpdf = lpdf_epdf.load
+ local closepdf = lpdf_epdf.unload
+
+ local function newpdf(str,userpassword,ownerpassword)
+ return openpdf(str,userpassword,ownerpassword,true)
+ end
+
+ local function querypdf(pdfdoc,pagenumber)
+ if pdfdoc then
+ if not pagenumber then
+ pagenumber = 1
+ end
+ local root = pdfdoc.Catalog
+ local page = pdfdoc.pages[pagenumber]
+ if page then
+ -- todo
+ local mediabox = page.MediaBox or { 0, 0, 0, 0 }
+ local cropbox = page.CropBox or mediabox
+ return {
+ filename = pdfdoc.filename,
+ pagenumber = pagenumber,
+ nofpages = pdfdoc.nofpages,
+ boundingbox = scaledbbox(cropbox),
+ cropbox = cropbox,
+ mediabox = mediabox,
+ bleedbox = page.BleedBox or cropbox,
+ trimbox = page.TrimBox or cropbox,
+ artbox = page.ArtBox or cropbox,
+ rotation = page.Rotate or 0,
+ xsize = cropbox[3] - cropbox[1],
+ ysize = cropbox[4] - cropbox[2],
+ }
+ end
+ end
+ end
+
+ local function copypage(pdfdoc,pagenumber,attributes,compact,width,height,attr)
+ if pdfdoc then
+ local root = pdfdoc.Catalog
+ local page = pdfdoc.pages[pagenumber or 1]
+ local pageinfo = querypdf(pdfdoc,pagenumber)
+ local contents = page.Contents
+ local xref = pdfdoc.__xrefs__
+ local copied = pdfdoc.__copied__
+ if compact and lpdf_epdf.plugin then
+ plugins = lpdf_epdf.plugin(pdfdoc,xref,copied,page)
+ end
+ local xobject = pdfdictionary {
+ Type = pdfconstant("XObject"),
+ Subtype = pdfconstant("Form"),
+ FormType = 1,
+ Group = copyobject(xref,copied,page,"Group"),
+ LastModified = copyobject(xref,copied,page,"LastModified"),
+ Metadata = copyobject(xref,copied,page,"Metadata"),
+ PieceInfo = copyobject(xref,copied,page,"PieceInfo"),
+ Resources = copyresources(pdfdoc,xref,copied,page),
+ SeparationInfo = copyobject(xref,copied,page,"SeparationInfo"),
+ } + attr
+ if attributes then
+ for k, v in expanded(attributes) do
+ page[k] = v -- maybe nested
+ end
+ end
+ local content = ""
+ local nolength = nil
+ local ctype = contents.__type__
+ -- we always recompress because image object streams can not be
+ -- influenced (yet)
+ if ctype == stream_object_code then
+ if stripmarked then
+ content = contents() -- uncompressed
+ local stripped = lpdf_epdf.stripcontent(content)
+ if stripped ~= content then
+ -- report("%i bytes stripped on page %i",#content-#stripped,pagenumber or 1)
+ content = stripped
+ end
+ elseif recompress then
+ content = contents() -- uncompressed
+ else
+ local Filter = copyobject(xref,copied,contents,"Filter")
+ local Length = copyobject(xref,copied,contents,"Length")
+ if Length and Filter then
+ nolength = true
+ xobject.Length = Length
+ xobject.Filter = Filter
+ content = contents(false) -- uncompressed
+ else
+ content = contents() -- uncompressed
+ end
+ end
+ elseif ctype == array_object_code then
+ content = { }
+ for i=1,#contents do
+ content[i] = contents[i]() -- uncompressed
+ end
+ content = concat(content," ")
+ end
+ -- still not nice: we double wrap now
+ plugins = nil
+ local rotation = pageinfo.rotation
+ local boundingbox = pageinfo.boundingbox
+ local transform = nil
+ if rotation == 90 then
+ transform = 3
+ elseif rotation == 180 then
+ transform = 2
+ elseif rotation == 270 then
+ transform = 1
+ elseif rotation > 1 and rotation < 4 then
+ transform = rotation
+ end
+ xobject.BBox = pdfarray {
+ boundingbox[1] * bpfactor,
+ boundingbox[2] * bpfactor,
+ boundingbox[3] * bpfactor,
+ boundingbox[4] * bpfactor,
+ }
+ -- maybe like bitmaps
+ return createimage { -- beware: can be a img.new or a dummy
+ bbox = boundingbox,
+ transform = transform,
+ nolength = nolength,
+ nobbox = true,
+ notype = true,
+ stream = content, -- todo: no compress, pass directly also length, filter etc
+ attr = xobject(),
+ kind = images.types.stream,
+ }
+ end
+ end
+
+ lpdf_epdf.image = {
+ open = openpdf,
+ close = closepdf,
+ new = newpdf,
+ query = querypdf,
+ copy = copypage,
+ }
+
+-- lpdf.injectors.pdf = function(specification)
+-- local d = lpdf_epdf.load(specification.filename)
+-- print(d)
+-- end
+
+
+end end
+
+-- local d = lpdf_epdf.load("e:/tmp/oeps.pdf")
+-- inspect(d)
+-- inspect(d.Catalog.Lang)
+-- inspect(d.Catalog.OCProperties.D.AS[1].Event)
+-- inspect(d.Catalog.Metadata())
+-- inspect(d.Catalog.Pages.Kids[1])
+-- inspect(d.layers)
+-- inspect(d.pages)
+-- inspect(d.destinations)
+-- inspect(lpdf_epdf.getpagecontent(d,1))
+-- inspect(lpdf_epdf.contenttotext(document,lpdf_epdf.getpagecontent(d,1)))
+-- inspect(lpdf_epdf.getstructure(document,lpdf_epdf.getpagecontent(d,1)))
diff --git a/tex/context/base/mkiv/lpdf-pdx.xml b/tex/context/base/mkiv/lpdf-pdx.xml
index 889862c76..35726a5c0 100644
--- a/tex/context/base/mkiv/lpdf-pdx.xml
+++ b/tex/context/base/mkiv/lpdf-pdx.xml
@@ -29,6 +29,7 @@
<pdfx:ConTeXt.Url/>
<pdfx:ConTeXt.Support/>
<pdfx:ConTeXt.Version/>
+ <pdfx:ConTeXt.LMTX/>
<pdfx:TeX.Support/>
<pdfx:LuaTeX.Version/>
<pdfx:LuaTeX.Functionality/>
diff --git a/tex/context/base/mkiv/lpdf-pua.xml b/tex/context/base/mkiv/lpdf-pua.xml
index f985b54d3..f717762b6 100644
--- a/tex/context/base/mkiv/lpdf-pua.xml
+++ b/tex/context/base/mkiv/lpdf-pua.xml
@@ -29,6 +29,7 @@
<pdfx:ConTeXt.Url/>
<pdfx:ConTeXt.Support/>
<pdfx:ConTeXt.Version/>
+ <pdfx:ConTeXt.LMTX/>
<pdfx:TeX.Support/>
<pdfx:LuaTeX.Version/>
<pdfx:LuaTeX.Functionality/>
@@ -112,14 +113,50 @@
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>ConTeXt support</pdfaProperty:description>
+ <pdfaProperty:name>ConTeXt.Support</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>external</pdfaProperty:category>
<pdfaProperty:description>ConTeXt version</pdfaProperty:description>
<pdfaProperty:name>ConTeXt.Version</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<pdfaProperty:category>external</pdfaProperty:category>
- <pdfaProperty:description>Banner of pdftex or one of its successors</pdfaProperty:description>
- <pdfaProperty:name>PTEX.Fullbanner</pdfaProperty:name>
+ <pdfaProperty:description>ConTeXt LMTX version</pdfaProperty:description>
+ <pdfaProperty:name>ConTeXt.LMTX</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>TeX support</pdfaProperty:description>
+ <pdfaProperty:name>TeX.Support</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>LuaTeX version</pdfaProperty:description>
+ <pdfaProperty:name>LuaTeX.Version</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>LuaTeX functionality</pdfaProperty:description>
+ <pdfaProperty:name>LuaTeX.Functionality</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>LuaTeX Lua version</pdfaProperty:description>
+ <pdfaProperty:name>LuaTeX.LuaVersion</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>LuaTeX platform</pdfaProperty:description>
+ <pdfaProperty:name>LuaTeX.Platform</pdfaProperty:name>
<pdfaProperty:valueType>Text</pdfaProperty:valueType>
</rdf:li>
<rdf:li rdf:parseType="Resource">
diff --git a/tex/context/base/mkiv/lpdf-ren.lua b/tex/context/base/mkiv/lpdf-ren.lua
index e9b22f382..d6e95e66a 100644
--- a/tex/context/base/mkiv/lpdf-ren.lua
+++ b/tex/context/base/mkiv/lpdf-ren.lua
@@ -54,7 +54,7 @@ local copy_node = nuts.copy
local nodepool = nuts.pool
local register = nodepool.register
-local pdfpageliteral = nodepool.pdfpageliteral
+local pageliteral = nodepool.pageliteral
local pdf_ocg = pdfconstant("OCG")
local pdf_ocmd = pdfconstant("OCMD")
@@ -261,7 +261,7 @@ function nodeinjections.startlayer(name)
local c = cache[name]
if not c then
useviewerlayer(name)
- c = register(pdfpageliteral(f_bdc(escapednames[name])))
+ c = register(pageliteral(f_bdc(escapednames[name])))
cache[name] = c
end
return copy_node(c)
@@ -269,7 +269,7 @@ end
function nodeinjections.stoplayer()
if not stop then
- stop = register(pdfpageliteral(s_emc))
+ stop = register(pageliteral(s_emc))
end
return copy_node(stop)
end
@@ -286,7 +286,7 @@ function nodeinjections.startstackedlayer(s,t,first,last)
r[#r+1] = startlayer(values[t[i]])
end
r = concat(r," ")
- return pdfpageliteral(r)
+ return pageliteral(r)
end
function nodeinjections.stopstackedlayer(s,t,first,last)
@@ -295,7 +295,7 @@ function nodeinjections.stopstackedlayer(s,t,first,last)
r[#r+1] = stoplayer()
end
r = concat(r," ")
- return pdfpageliteral(r)
+ return pageliteral(r)
end
function nodeinjections.changestackedlayer(s,t1,first1,last1,t2,first2,last2)
@@ -307,7 +307,7 @@ function nodeinjections.changestackedlayer(s,t1,first1,last1,t2,first2,last2)
r[#r+1] = startlayer(values[t2[i]])
end
r = concat(r," ")
- return pdfpageliteral(r)
+ return pageliteral(r)
end
-- transitions
diff --git a/tex/context/base/mkiv/lpdf-res.lua b/tex/context/base/mkiv/lpdf-res.lua
index 8b00835ef..d3c591343 100644
--- a/tex/context/base/mkiv/lpdf-res.lua
+++ b/tex/context/base/mkiv/lpdf-res.lua
@@ -6,23 +6,25 @@ if not modules then modules = { } end modules ['lpdf-res'] = {
license = "see context related readme files"
}
-local codeinjections = backends.codeinjections
-local implement = interfaces.implement
+local codeinjections = backends.codeinjections
-local nuts = nodes.nuts
-local tonut = nodes.tonut
+local nuts = nodes.nuts
+local tonut = nodes.tonut
-local setwhd = nuts.setwhd
-local setlist = nuts.setlist
+local setwhd = nuts.setwhd
+local setlist = nuts.setlist
-local new_hlist = nuts.pool.hlist
+local new_hlist = nuts.pool.hlist
-local saveboxresource = tex.saveboxresource
-local useboxresource = tex.useboxresource
-local getboxresource = tex.getboxresourcedimensions
+local boxresources = tex.boxresources
+local saveboxresource = boxresources.save
+local useboxresource = boxresources.use
+local getboxresourcedimensions = boxresources.getdimensions
+
+local pdfcollectedresources = lpdf.collectedresources
function codeinjections.registerboxresource(n,offset)
- local r = saveboxresource(n,nil,lpdf.collectedresources(),true,0,offset or 0) -- direct, todo: accept functions as attr/resources
+ local r = saveboxresource(n,nil,pdfcollectedresources(),true,0,offset or 0) -- direct, todo: accept functions as attr/resources
return r
end
@@ -35,5 +37,5 @@ function codeinjections.restoreboxresource(index)
end
function codeinjections.boxresourcedimensions(index)
- return getboxresource(index)
+ return getboxresourcedimensions(index)
end
diff --git a/tex/context/base/mkiv/lpdf-swf.lua b/tex/context/base/mkiv/lpdf-swf.lua
index 0ac107f8b..44e42dc5f 100644
--- a/tex/context/base/mkiv/lpdf-swf.lua
+++ b/tex/context/base/mkiv/lpdf-swf.lua
@@ -11,6 +11,7 @@ if not modules then modules = { } end modules ['lpdf-swf'] = {
local format, gsub = string.format, string.gsub
local concat = table.concat
+local formatters = string.formatters
local backends = backends
local lpdf = lpdf
@@ -33,6 +34,43 @@ local trace_swf = false trackers.register("backend.swf", function(v) trace_swf
local report_swf = logs.reporter("backend","swf")
+--------------------------------------------------------------------------------------
+
+local createimage = images.create
+local embedimage = images.embed
+
+local basepoints = number.dimenfactors.bp
+
+local f_image = formatters["%.6F 0 0 %.6F 0 0 cm /%s Do"]
+
+directives.register("pdf.stripzeros",function()
+ f_image = formatters["%.6N 0 0 %.6N 0 0 cm /%s Do"]
+end)
+
+local function package(image) -- see lpdf-u3d **
+ local boundingbox = image.bbox
+ local imagetag = "Im" .. image.index -- this is not ok
+ local resources = pdfdictionary {
+ ProcSet = lpdf.procset(),
+ Resources = pdfdictionary {
+ XObject = pdfdictionary {
+ [imagetag] = pdfreference(image.objnum)
+ }
+ }
+ }
+ local width = boundingbox[3]
+ local height = boundingbox[4]
+ local xform = createimage {
+ attr = resources(),
+ stream = f_image(width,height,imagetag),
+ bbox = { 0, 0, width/basepoints, height/basepoints },
+ }
+ embedimage(xform)
+ return xform
+end
+
+--------------------------------------------------------------------------------------
+
local activations = {
click = "XA",
page = "PO",
@@ -65,7 +103,10 @@ local function insertswf(spec)
local preview = checkedkey(display,"preview","string")
local toolbar = checkedkey(display,"toolbar","boolean")
- local embeddedreference = codeinjections.embedfile { file = filename }
+ local embeddedreference = codeinjections.embedfile {
+ file = filename,
+ compress = false,
+ }
local flash = pdfdictionary {
Subtype = pdfconstant("RichMediaConfiguration"),
@@ -122,6 +163,7 @@ local function insertswf(spec)
file = fullname,
usedname = usedname,
keepdir = true,
+ compress = false,
}
names[#names+1] = pdfstring(filename)
names[#names+1] = embeddedreference
@@ -275,7 +317,7 @@ local function insertswf(spec)
end
end
if figure then
- local image = img.package(figure.status.private)
+ local image = package(figure.status.private)
appearance = pdfdictionary { N = pdfreference(image.objnum) }
if trace_swf then
report_swf("using preview %s",preview)
diff --git a/tex/context/base/mkiv/lpdf-tag.lua b/tex/context/base/mkiv/lpdf-tag.lua
index f4ecfc8a6..0a2fe679e 100644
--- a/tex/context/base/mkiv/lpdf-tag.lua
+++ b/tex/context/base/mkiv/lpdf-tag.lua
@@ -13,7 +13,8 @@ local settings_to_hash = utilities.parsers.settings_to_hash
local sortedhash = table.sortedhash
local formatters = string.formatters
-local trace_tags = false trackers.register("structures.tags", function(v) trace_tags = v end)
+local trace_tags = false trackers.register("structures.tags", function(v) trace_tags = v end)
+local trace_info = false trackers.register("structures.tags.info", function(v) trace_info = v end)
local report_tags = logs.reporter("backend","tags")
@@ -51,11 +52,9 @@ local a_tagged = attributes.private('tagged')
local a_image = attributes.private('image')
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local nodepool = nuts.pool
-local pdfpageliteral = nodepool.pdfpageliteral
+local pageliteral = nodepool.pageliteral
local register = nodepool.register
local getid = nuts.getid
@@ -68,17 +67,17 @@ local setlink = nuts.setlink
local setlist = nuts.setlist
local copy_node = nuts.copy
-local traverse_nodes = nuts.traverse
local tosequence = nuts.tosequence
-local structure_stack = { }
-local structure_kids = pdfarray()
-local structure_ref = pdfreserveobject()
-local parent_ref = pdfreserveobject()
-local root = { pref = pdfreference(structure_ref), kids = structure_kids }
+local nextnode = nuts.traversers.node
+
+local structure_kids -- delayed
+local structure_ref -- delayed
+local parent_ref -- delayed
+local root -- delayed
+local names -- delayed
local tree = { }
local elements = { }
-local names = pdfarray()
local structurestags = structures.tags
local taglist = structurestags.taglist
@@ -112,7 +111,7 @@ local usedmapping = { }
-- end
local function finishstructure()
- if #structure_kids > 0 then
+ if root and #structure_kids > 0 then
local nums, n = pdfarray(), 0
for i=1,#tree do
n = n + 1 ; nums[n] = i - 1
@@ -171,6 +170,7 @@ local index, pageref, pagenum, list = 0, nil, 0, nil
local pdf_mcr = pdfconstant("MCR")
local pdf_struct_element = pdfconstant("StructElem")
+local pdf_s = pdfconstant("S")
local function initializepage()
index = 0
@@ -183,6 +183,8 @@ end
local function finishpage()
-- flush what can be flushed
addtopageattributes("StructParents",pagenum-1)
+ -- there might be more
+ addtopageattributes("Tabs",s)
end
-- here we can flush and free elements that are finished
@@ -255,9 +257,10 @@ local function makeelement(fulltag,parent)
AF = af,
}
local s = pdfreference(pdfflushobject(d))
- if id then
- names[#names+1] = id
- names[#names+1] = s
+ if id and names then
+ local size = #names
+ names[size+1] = id
+ names[size+2] = s
end
local kids = parent.kids
kids[#kids+1] = s
@@ -314,27 +317,35 @@ end
-- no need to adapt head, as we always operate on lists
local EMCliteral = nil
+local visualize = nil
function nodeinjections.addtags(head)
if not EMCliteral then
- EMCliteral = register(pdfpageliteral("EMC"))
+ EMCliteral = register(pageliteral("EMC"))
end
local last = nil
local ranges = { }
local range = nil
- local head = tonut(head)
+
+ if not root then
+ structure_kids = pdfarray()
+ structure_ref = pdfreserveobject()
+ parent_ref = pdfreserveobject()
+ root = { pref = pdfreference(structure_ref), kids = structure_kids }
+ names = pdfarray()
+ end
local function collectranges(head,list)
- for n in traverse_nodes(head) do
- local id = getid(n)
+ for n, id in nextnode, head do
if id == glyph_code then
-- maybe also disc
- local at = getattr(n,a_tagged)
- if not at then
- range = nil
- elseif last ~= at then
+ local at = getattr(n,a_tagged) or false -- false: pagebody or so, so artifact
+ -- if not at then
+ -- range = nil
+ -- elseif ...
+ if last ~= at then
range = { at, "glyph", n, n, list } -- attr id start stop list
ranges[#ranges+1] = range
last = at
@@ -344,12 +355,12 @@ function nodeinjections.addtags(head)
elseif id == hlist_code or id == vlist_code then
local at = getattr(n,a_image)
if at then
- local at = getattr(n,a_tagged)
- if not at then
- range = nil
- else
+ local at = getattr(n,a_tagged) or false -- false: pagebody or so, so artifact
+ -- if not at then
+ -- range = nil
+ -- else
ranges[#ranges+1] = { at, "image", n, n, list } -- attr id start stop list
- end
+ -- end
last = nil
else
collectranges(getlist(n),n)
@@ -379,89 +390,117 @@ function nodeinjections.addtags(head)
local top = nil
local noftop = 0
+
+ local function inject(start,stop,list,literal,left,right)
+ local prev = getprev(start)
+ if prev then
+ setlink(prev,literal)
+ end
+ if left then
+ setlink(literal,left,start)
+ else
+ setlink(literal,start)
+ end
+ if list and getlist(list) == start then
+ setlist(list,literal)
+ end
+ local literal = copy_node(EMCliteral)
+ -- use insert instead:
+ local next = getnext(stop)
+ if next then
+ setlink(literal,next)
+ end
+ if right then
+ setlink(stop,right,literal)
+ else
+ setlink(stop,literal)
+ end
+ end
+
for i=1,#ranges do
- local range = ranges[i]
- local attr = range[1]
- local id = range[2]
- local start = range[3]
- local stop = range[4]
- local list = range[5]
- local specification = taglist[attr]
- local taglist = specification.taglist
- local noftags = #taglist
- local common = 0
- if top then
- for i=1,noftags >= noftop and noftop or noftags do
- if top[i] == taglist[i] then
- common = i
- else
- break
+
+ local range = ranges[i]
+ local attr = range[1]
+ local id = range[2]
+ local start = range[3]
+ local stop = range[4]
+ local list = range[5]
+
+ if attr then
+
+ local specification = taglist[attr]
+ local taglist = specification.taglist
+ local noftags = #taglist
+ local common = 0
+ local literal = nil
+ local ignore = false
+
+ if top then
+ for i=1,noftags >= noftop and noftop or noftags do
+ if top[i] == taglist[i] then
+ common = i
+ else
+ break
+ end
end
end
- end
- local prev = common > 0 and elements[taglist[common]] or root
- local ignore = false
- local literal = nil
-
- for j=common+1,noftags do
- local tag = taglist[j]
- local prv = elements[tag] or makeelement(tag,prev)
- if prv == false then
- -- ignore this one
- prev = false
- ignore = true
- break
- elseif prv == true then
- -- skip this one
- else
- prev = prv
+ local prev = common > 0 and elements[taglist[common]] or root
+
+ for j=common+1,noftags do
+ local tag = taglist[j]
+ local prv = elements[tag] or makeelement(tag,prev)
+ if prv == false then
+ -- ignore this one
+ prev = false
+ ignore = true
+ break
+ elseif prv == true then
+ -- skip this one
+ else
+ prev = prv
+ end
end
- end
- if prev then
- literal = pdfpageliteral(makecontent(prev,id,specification))
- elseif ignore then
- literal = pdfpageliteral(makeignore(specification))
- end
- if literal then
- local prev = getprev(start)
if prev then
- setlink(prev,literal)
- end
- setlink(literal,start)
- if list and getlist(list) == start then
- setlist(list,literal)
+ literal = pageliteral(makecontent(prev,id,specification))
+ elseif ignore then
+ literal = pageliteral(makeignore(specification))
+ else
+ -- maybe also ignore or maybe better: comment or so
end
- local literal = copy_node(EMCliteral)
- -- use insert instead:
- local next = getnext(stop)
- if next then
- setlink(literal,next)
+
+ if literal then
+ local left,right
+ if trace_info then
+ local name = specification.tagname
+ if name then
+ if not visualize then
+ visualize = nodes.visualizers.register("tags")
+ end
+ left = visualize(name)
+ right = visualize()
+ end
+ end
+ inject(start,stop,list,literal,left,right)
end
- setlink(stop,literal)
- end
--- if literal then
--- if list and getlist(list) == start then
--- setlink(literal,start)
--- setlist(list,literal)
--- else
--- setlink(getprev(start),literal,start)
--- end
--- -- use insert instead:
--- local literal = copy_node(EMCliteral)
--- setlink(stop,literal,getnext(stop))
--- end
+ top = taglist
+ noftop = noftags
+
+ else
+
+ local literal = pageliteral(makeignore(specification))
+
+ inject(start,stop,list,literal)
+
+ end
- top = taglist
- noftop = noftags
end
finishpage()
- head = tonode(head)
- return head, true
+ return head
end
@@ -472,8 +511,7 @@ end
-- local last, ranges, range = nil, { }, nil
--
-- local function collectranges(head,list)
--- for n in traverse_nodes(head) do
--- local id = getid(n) -- 14: image, 8: literal (mp)
+-- for n, id in nextnode, head do
-- if id == glyph_code then
-- local at = getattr(n,a_tagged)
-- if not at then
@@ -505,7 +543,6 @@ end
--
-- initializepage()
--
--- head = tonut(head)
-- collectranges(head)
--
-- if trace_tags then
@@ -577,9 +614,9 @@ end
-- end
--
-- if r > 0 then
--- local literal = pdfpageliteral(concat(result,"\n"))
+-- local literal = pageliteral(concat(result,"\n"))
-- -- use insert instead:
--- local literal = pdfpageliteral(result)
+-- local literal = pageliteral(result)
-- local prev = getprev(start)
-- if prev then
-- setlink(prev,literal)
@@ -601,7 +638,7 @@ end
-- for i=1,noftop do
-- result[i] = "EMC"
-- end
--- local literal = pdfpageliteral(concat(result,"\n"))
+-- local literal = pageliteral(concat(result,"\n"))
-- -- use insert instead:
-- local next = getnext(last)
-- if next then
@@ -612,8 +649,7 @@ end
--
-- finishpage()
--
--- head = tonode(head)
--- return head, true
+-- return head
--
-- end
diff --git a/tex/context/base/mkiv/lpdf-u3d.lua b/tex/context/base/mkiv/lpdf-u3d.lua
index dfd4c1b06..f6897e92d 100644
--- a/tex/context/base/mkiv/lpdf-u3d.lua
+++ b/tex/context/base/mkiv/lpdf-u3d.lua
@@ -27,7 +27,6 @@ local nodeinjections = backends.pdf.nodeinjections
local pdfconstant = lpdf.constant
local pdfboolean = lpdf.boolean
-local pdfnumber = lpdf.number
local pdfunicode = lpdf.unicode
local pdfdictionary = lpdf.dictionary
local pdfarray = lpdf.array
@@ -39,6 +38,8 @@ local pdfflushstreamfileobject = lpdf.flushstreamfileobject
local checkedkey = lpdf.checkedkey
local limited = lpdf.limited
+local embedimage = images.embed
+
local schemes = table.tohash {
"Artwork", "None", "White", "Day", "Night", "Hard",
"Primary", "Blue", "Red", "Cube", "CAD", "Headlamp",
@@ -347,6 +348,12 @@ end
local stored_js, stored_3d, stored_pr, streams = { }, { }, { }, { }
+local f_image = formatters["q /GS gs %.6F 0 0 %.6F 0 0 cm /IM Do Q"]
+
+directives.register("pdf.stripzeros",function()
+ f_image = formatters["q /GS gs %.6N 0 0 %.6N 0 0 cm /IM Do Q"]
+end)
+
local function insert3d(spec) -- width, height, factor, display, controls, label, foundname
local width, height, factor = spec.width, spec.height, spec.factor or number.dimenfactors.bp
@@ -431,7 +438,7 @@ local function insert3d(spec) -- width, height, factor, display, controls, label
local tag = formatters["%s:%s:%s"](label,stream,preview)
local ref = stored_pr[tag]
if not ref then
- local figure = img.immediatewrite {
+ local figure = embedimage {
filename = preview,
width = width,
height = height
@@ -440,13 +447,13 @@ local function insert3d(spec) -- width, height, factor, display, controls, label
stored_pr[tag] = ref
end
if ref then -- see back-pdf ** .. here we have a local /IM !
- local zero, one = pdfnumber(0), pdfnumber(1) -- not really needed
local pw = pdfdictionary {
Type = pdfconstant("XObject"),
Subtype = pdfconstant("Form"),
- FormType = one,
- BBox = pdfarray { zero, zero, pdfnumber(factor*width), pdfnumber(factor*height) },
- Matrix = pdfarray { one, zero, zero, one, zero, zero },
+ FormType = 1,
+ BBox = pdfarray { 0, 0, pdfnumber(factor*width), pdfnumber(factor*height) },
+ Matrix = pdfarray { 1, 0, 0, 1, 0, 0 },
+ ProcSet = lpdf.procset(),
Resources = pdfdictionary {
XObject = pdfdictionary {
IM = pdfreference(ref)
@@ -455,13 +462,12 @@ local function insert3d(spec) -- width, height, factor, display, controls, label
ExtGState = pdfdictionary {
GS = pdfdictionary {
Type = pdfconstant("ExtGState"),
- CA = one,
- ca = one,
+ CA = 1,
+ ca = 1,
}
},
- ProcSet = pdfarray { pdfconstant("PDF"), pdfconstant("ImageC") },
}
- local pwd = pdfflushstreamobject(formatters["q /GS gs %.6F 0 0 %.6F 0 0 cm /IM Do Q"](factor*width,factor*height),pw)
+ local pwd = pdfflushstreamobject(f_image(factor*width,factor*height),pw)
annot.AP = pdfdictionary {
N = pdfreference(pwd)
}
diff --git a/tex/context/base/mkiv/lpdf-wid.lua b/tex/context/base/mkiv/lpdf-wid.lua
index 03febbf01..a929ed2ce 100644
--- a/tex/context/base/mkiv/lpdf-wid.lua
+++ b/tex/context/base/mkiv/lpdf-wid.lua
@@ -11,11 +11,11 @@ if not modules then modules = { } end modules ['lpdf-wid'] = {
-- had renditions but they turned out to be unreliable from the start and look
-- obsolete too or at least they are bound to the (obsolete) flash technology for
-- rendering. They were already complex constructs. Now we have rich media which
--- instead of providing a robust future proof framework fo rgeneral media types
+-- instead of providing a robust future proof framework for general media types
-- again seems to depend on viewers built in (yes, also kind of obsolete) flash
-- technology, and we cannot expect this non-open technology to show up in open
-- browsers. So, in the end we can best just use links to external resources to be
--- future proof. Just look at the viewer prferences pane to see how fragile support
+-- future proof. Just look at the viewer preferences pane to see how fragile support
-- is. Interestingly u3d support is kind of built in, while e.g. mp4 support relies
-- on wrapping in swf. We used to stay ahead of the pack with support of the fancy
-- pdf features but it backfires and is not worth the trouble. And yes, for control
@@ -29,7 +29,7 @@ local gmatch, gsub, find, lower = string.gmatch, string.gsub, string.find, strin
local stripstring = string.strip
local settings_to_array = utilities.parsers.settings_to_array
local settings_to_hash = utilities.parsers.settings_to_hash
-local sortedhash = table.sortedhash
+local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys
local report_media = logs.reporter("backend","media")
local report_attachment = logs.reporter("backend","attachment")
@@ -141,6 +141,10 @@ local attachment_symbols = {
attachment_symbols.PushPin = attachment_symbols.Pushpin
attachment_symbols.Default = attachment_symbols.Pushpin
+function lpdf.attachmentsymbols()
+ return sortedkeys(comment_symbols)
+end
+
local comment_symbols = {
Comment = pdfconstant("Comment"),
Help = pdfconstant("Help"),
@@ -154,6 +158,10 @@ local comment_symbols = {
comment_symbols.NewParagraph = Newparagraph
comment_symbols.Default = Note
+function lpdf.commentsymbols()
+ return sortedkeys(comment_symbols)
+end
+
local function analyzesymbol(symbol,collection)
if not symbol or symbol == "" then
return collection and collection.Default, nil
@@ -239,10 +247,12 @@ local function flushembeddedfiles()
e[#e+1] = pdfstring(tag)
e[#e+1] = reference -- already a reference
else
- -- messy spec ... when annot not in named else twice in menu list acrobat
+ -- -- messy spec ... when annot not in named else twice in menu list acrobat
end
end
- lpdf.addtonames("EmbeddedFiles",pdfreference(pdfflushobject(pdfdictionary{ Names = e })))
+ if #e > 0 then
+ lpdf.addtonames("EmbeddedFiles",pdfreference(pdfflushobject(pdfdictionary{ Names = e })))
+ end
end
end
@@ -257,9 +267,13 @@ function codeinjections.embedfile(specification)
local keepdir = specification.keepdir -- can change
local usedname = specification.usedname
local filetype = specification.filetype
+ local compress = specification.compress
if filename == "" then
filename = nil
end
+ if compress == nil then
+ compress = true
+ end
if data then
local r = filestreams[hash]
if r == false then
@@ -314,7 +328,7 @@ function codeinjections.embedfile(specification)
specification.data = true -- signal that still data but already flushed
else
local foundname = specification.foundname or filename
- f = pdfflushstreamfileobject(foundname,a)
+ f = pdfflushstreamfileobject(foundname,a,compress)
end
local d = pdfdictionary {
Type = pdfconstant("Filespec"),
@@ -417,7 +431,8 @@ function codeinjections.attachmentid(filename) -- not used in context
return filestreams[filename]
end
-local nofcomments, usepopupcomments = 0, false
+local nofcomments = 0
+local usepopupcomments = false
local defaultattributes = {
["xmlns"] = "http://www.w3.org/1999/xhtml",
@@ -612,7 +627,8 @@ local function insertrendering(specification)
local option = settings_to_hash(specification.option)
if not mf[label] then
local filename = specification.filename
- local isurl = find(filename,"://",1,true)
+ local isurl = find(filename,"://",1,true)
+ local mimetype = specification.mimetype or specification.mime
-- local start = pdfdictionary {
-- Type = pdfconstant("MediaOffset"),
-- S = pdfconstant("T"), -- time
@@ -648,13 +664,17 @@ local function insertrendering(specification)
if isurl then
descriptor.FS = pdfconstant("URL")
elseif option[v_embed] then
- descriptor.EF = codeinjections.embedfile { file = filename }
+ descriptor.EF = codeinjections.embedfile {
+ file = filename,
+ mimetype = mimetype, -- yes or no
+ compress = false,
+ }
end
local clip = pdfdictionary {
Type = pdfconstant("MediaClip"),
S = pdfconstant("MCD"),
N = label,
- CT = specification.mime,
+ CT = mimetype,
Alt = pdfarray { "", "file not found" }, -- language id + message
D = pdfreference(pdfflushobject(descriptor)),
-- P = pdfreference(pdfflushobject(parameters)),
diff --git a/tex/context/base/mkiv/lpdf-xmp.lua b/tex/context/base/mkiv/lpdf-xmp.lua
index eb15a3582..508bb1997 100644
--- a/tex/context/base/mkiv/lpdf-xmp.lua
+++ b/tex/context/base/mkiv/lpdf-xmp.lua
@@ -11,6 +11,7 @@ local tostring, type = tostring, type
local format, gsub = string.format, string.gsub
local utfchar = utf.char
local xmlfillin = xml.fillin
+local md5HEX = md5.HEX
local trace_xmp = false trackers.register("backend.xmp", function(v) trace_xmp = v end)
local trace_info = false trackers.register("backend.info", function(v) trace_info = v end)
@@ -33,7 +34,7 @@ local pdfgetmetadata = lpdf.getmetadata
-- XMP-Toolkit-SDK-CC201607.zip. So we hardcode the id.
local xpacket = format ( [[
-<?xpacket begin="%s" id="W5M0MpCehiHzreSzNTczkc9d"?>
+<?xpacket begin="%s" id="W5M0MpCehiHzreSzNTczkc9d"?>
%%s
@@ -46,7 +47,8 @@ local mapping = {
["ConTeXt.Url"] = { "context", "rdf:Description/pdfx:ConTeXt.Url" },
["ConTeXt.Support"] = { "context", "rdf:Description/pdfx:ConTeXt.Support" },
["ConTeXt.Version"] = { "context", "rdf:Description/pdfx:ConTeXt.Version" },
- ["TeX.Support"] = { "metadata", "rdf:Description/pdfx:TeX.Support" },
+ ["ConTeXt.LMTX"] = { "context", "rdf:Description/pdfx:ConTeXt.LMTX" },
+ ["TeX.Support"] = { "metadata","rdf:Description/pdfx:TeX.Support" },
["LuaTeX.Version"] = { "metadata","rdf:Description/pdfx:LuaTeX.Version" },
["LuaTeX.Functionality"] = { "metadata","rdf:Description/pdfx:LuaTeX.Functionality" },
["LuaTeX.LuaVersion"] = { "metadata","rdf:Description/pdfx:LuaTeX.LuaVersion" },
@@ -89,7 +91,7 @@ local mapping = {
["CaptionWriter"] = { "metadata", "rdf:Description/photoshop:CaptionWriter" },
}
-pdf.setsuppressoptionalinfo(
+lpdf.setsuppressoptionalinfo (
0 --
+ 1 -- pdfnofullbanner
+ 2 -- pdfnofilename
@@ -104,59 +106,62 @@ pdf.setsuppressoptionalinfo(
)
local included = backends.included
-
-local pdfsettrailerid = pdf.settrailerid
-
-local lpdfid = lpdf.id
+local lpdfid = lpdf.id
function lpdf.id() -- overload of ini
return lpdfid(included.date)
end
-pdf.disablecommand("settrailerid")
+local settrailerid = lpdf.settrailerid -- this is the wrapped one
+
+local trailerid = nil
+local dates = nil
-function lpdf.settrailerid(v)
- if v then
- local b = toboolean(v) or v == ""
+local function update()
+ if trailer_id then
+ local b = toboolean(trailer_id) or trailer_id == ""
if b then
- v = "This file is processed by ConTeXt and LuaTeX."
+ trailer_id = "This file is processed by ConTeXt and LuaTeX."
else
- v = tostring(v)
+ trailer_id = tostring(trailer_id)
end
- local h = md5.HEX(v)
+ local h = md5HEX(trailer_id)
if b then
report_info("using frozen trailer id")
else
- report_info("using hashed trailer id %a (%a)",v,h)
+ report_info("using hashed trailer id %a (%a)",trailer_id,h)
end
- pdfsettrailerid(format("[<%s> <%s>]",h,h))
+ settrailerid(format("[<%s> <%s>]",h,h))
end
-end
-
-function lpdf.setdates(v)
- local t = type(v)
+ --
+ local t = type(dates)
if t == "number" or t == "string" then
- t = converters.totime(v)
- if t then
+ local d = converters.totime(dates)
+ if d then
included.date = true
included.id = "fake"
- report_info("forced date/time information %a will be used",lpdf.settime(t))
- lpdf.settrailerid(false)
+ report_info("forced date/time information %a will be used",lpdf.settime(d))
+ settrailerid(false)
return
end
- end
- v = toboolean(v)
- included.date = v
- if v then
- included.id = true
- else
- report_info("no date/time but fake id information will be added")
- lpdf.settrailerid(true)
- included.id = "fake"
- -- maybe: lpdf.settime(231631200) -- 1975-05-05 % first entry of knuth about tex mentioned in DT
+ if t == "string" then
+ dates = toboolean(dates)
+ included.date = dates
+ if dates ~= false then
+ included.id = true
+ else
+ report_info("no date/time but fake id information will be added")
+ settrailerid(true)
+ included.id = "fake"
+ end
+ end
end
end
+function lpdf.settrailerid(v) trailerid = v end
+function lpdf.setdates (v) dates = v end
+
+lpdf.registerdocumentfinalizer(update,"trailer id and dates",1)
directives.register("backend.trailerid", lpdf.settrailerid)
directives.register("backend.date", lpdf.setdates)
@@ -313,7 +318,7 @@ local function flushxmpinfo()
commands.poprandomseed() -- hack
end
--- his will be enabled when we can inhibit compression for a stream at the lua end
+-- this will be enabled when we can inhibit compression for a stream at the lua end
lpdf.registerdocumentfinalizer(flushxmpinfo,1,"metadata")
diff --git a/tex/context/base/mkiv/luat-bas.mkiv b/tex/context/base/mkiv/luat-bas.mkiv
index b1af4da3e..0add4ce69 100644
--- a/tex/context/base/mkiv/luat-bas.mkiv
+++ b/tex/context/base/mkiv/luat-bas.mkiv
@@ -13,6 +13,7 @@
\writestatus{loading}{ConTeXt Lua Macros / Basic Lua Libraries}
+\registerctxluafile{l-bit32} {} % before sandbox
\registerctxluafile{l-lua} {} % before sandbox
\registerctxluafile{l-macro} {}
\registerctxluafile{l-sandbox} {}
@@ -30,6 +31,7 @@
\registerctxluafile{l-file} {}
\registerctxluafile{l-gzip} {}
\registerctxluafile{l-md5} {}
+\registerctxluafile{l-sha} {}
\registerctxluafile{l-dir} {}
\registerctxluafile{l-unicode} {optimize}
%registerctxluafile{l-utils} {}
diff --git a/tex/context/base/mkiv/luat-cbk.lua b/tex/context/base/mkiv/luat-cbk.lua
index 6fcfdc7f2..d3184e1af 100644
--- a/tex/context/base/mkiv/luat-cbk.lua
+++ b/tex/context/base/mkiv/luat-cbk.lua
@@ -121,6 +121,12 @@ if trace_calls then
end
+-- temporary, not public:
+
+callbacks.functions = { }
+
+-- till here
+
local reported = { }
local function register_usercall(what,name,func)
diff --git a/tex/context/base/mkiv/luat-cnf.lua b/tex/context/base/mkiv/luat-cnf.lua
index b6ee15083..0670d1684 100644
--- a/tex/context/base/mkiv/luat-cnf.lua
+++ b/tex/context/base/mkiv/luat-cnf.lua
@@ -154,6 +154,8 @@ function texconfig.init()
end
+CONTEXTLMTXMODE = %s
+
-- we provide a qualified path
callback.register('find_format_file',function(name)
@@ -212,7 +214,7 @@ local function makestub()
t[#t+1] = format("texconfig.%s=%s",v,tv)
end
end
- io.savedata(name,format("%s\n\n%s",concat(t,"\n"),format(stub,firsttable)))
+ io.savedata(name,format("%s\n\n%s",concat(t,"\n"),format(stub,firsttable,tostring(CONTEXTLMTXMODE) or 0)))
logs.newline()
end
diff --git a/tex/context/base/mkiv/luat-cod.lua b/tex/context/base/mkiv/luat-cod.lua
index 91bb7c2e1..dcb16c0dd 100644
--- a/tex/context/base/mkiv/luat-cod.lua
+++ b/tex/context/base/mkiv/luat-cod.lua
@@ -11,6 +11,10 @@ local match, gsub, find, format, gmatch = string.match, string.gsub, string.find
local texconfig, lua = texconfig, lua
+-- maybe pick up from commandline:
+--
+-- texconfig.interaction: 0=batchmode 1=nonstopmode 2=scrollmode 3=errornonstopmode 4=normal
+
-- some basic housekeeping
texconfig.kpse_init = false
@@ -38,7 +42,7 @@ lua.bytedata = bytedata
lua.bytedone = bytedone
local setbytecode = lua.setbytecode
-local getbytecode = lua.getbytecode
+----- getbytecode = lua.getbytecode
lua.firstbytecode = 501
lua.lastbytecode = lua.lastbytecode or (lua.firstbytecode - 1) -- as we load ourselves again ... maybe return earlier
@@ -49,9 +53,13 @@ end
-- no file.* and utilities.parsers.* functions yet
+local strip = false if arg then for i=-1,#arg do if arg[i] == "--c:strip" then strip = true break end end end
+
function lua.registercode(filename,options)
local barename = gsub(filename,"%.[%a%d]+$","")
- if barename == filename then filename = filename .. ".lua" end
+ if barename == filename then
+ filename = filename .. ".lua"
+ end
local basename = match(barename,"^.+[/\\](.-)$") or barename
if not bytedone[basename] then
local opts = { }
@@ -66,7 +74,11 @@ function lua.registercode(filename,options)
if environment.initex then
local n = lua.lastbytecode + 1
bytedata[n] = { name = barename, options = opts }
- setbytecode(n,code)
+ if strip or opts.strip then
+ setbytecode(n,code,true)
+ else
+ setbytecode(n,code)
+ end
lua.lastbytecode = n
end
elseif environment.initex then
@@ -129,6 +141,18 @@ if LUATEXVERION == nil then
+ (tonumber(LUATEXVERSION) or (string.byte(LUATEXVERSION)-string.byte("a")+10))/1000
end
+if CONTEXTLMTXMODE == nil then
+ if status.obj_ptr == nil then
+ CONTEXTLMTXMODE = 2
+ else
+ CONTEXTLMTXMODE = 0
+ for i=1,#arg do if arg[i] == "--c:lmtx" then
+ CONTEXTLMTXMODE, pdf, img = 1, nil, nil
+ break
+ end end
+ end
+end
+
if LUATEXFUNCTIONALITY == nil then
LUATEXFUNCTIONALITY = status.development_id or 6346
end
@@ -143,7 +167,7 @@ end
environment.luatexengine = LUATEXENGINE
environment.luatexversion = LUATEXVERSION
-environment.luatexfuncitonality = LUATEXFUNCTIONALITY
+environment.luatexfunctionality = LUATEXFUNCTIONALITY
environment.jitsupported = JITSUPPORTED
environment.initex = INITEXMODE
environment.initexmode = INITEXMODE
@@ -151,12 +175,14 @@ environment.initexmode = INITEXMODE
if not environment.luafilechunk then
function environment.luafilechunk(filename)
+ local fullname = filename
if sourcepath ~= "" then
- filename = sourcepath .. "/" .. filename
+ fullname = sourcepath .. "/" .. filename
end
- local data = loadfile(filename)
- texio.write("term and log","<",data and "+ " or "- ",filename,">")
+ local data = loadfile(fullname)
+ texio.write("term and log","<",data and "+ " or "- ",fullname,">")
if data then
+-- package.loaded[gsub(filename,"%..-$"] =
data()
end
return data
@@ -187,6 +213,21 @@ end
-- a kpse error when disabled. This is an engine issue that will
-- be sorted out in due time.
+if not lfs.isfile then
+
+ local attributes = lfs.attributes
+
+ function lfs.isdir(name)
+ return attributes(name,"mode") == "directory"
+ end
+
+ function lfs.isfile(name)
+ local a = attributes(name,"mode")
+ return a == "file" or a == "link" or nil
+ end
+
+end
+
local isfile = lfs.isfile
local function source_file(name)
@@ -229,6 +270,15 @@ local function open_read_file(name)
}
end
+local function find_data_file(name)
+ return source_file(name)
+end
+
+local open_data_file = open_read_file
+
callback.register('find_read_file' , find_read_file )
callback.register('open_read_file' , open_read_file )
callback.register('find_write_file', find_write_file)
+
+callback.register('find_data_file' , find_data_file )
+callback.register('open_data_file' , open_data_file )
diff --git a/tex/context/base/mkiv/luat-env.lua b/tex/context/base/mkiv/luat-env.lua
index 5b46b4036..e0c69d207 100644
--- a/tex/context/base/mkiv/luat-env.lua
+++ b/tex/context/base/mkiv/luat-env.lua
@@ -11,7 +11,8 @@
-- sense. Much of this evolved before bytecode arrays were available and so a lot of
-- code has disappeared already.
-local rawset, rawget, loadfile, assert = rawset, rawget, loadfile, assert
+local rawset, rawget, loadfile = rawset, rawget, loadfile
+local gsub = string.gsub
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -123,7 +124,7 @@ function environment.loadluafile(filename, version)
luaname = file.addsuffix(basename,luasuffixes.lua)
lucname = file.addsuffix(basename,luasuffixes.luc)
else
- luaname = basename -- forced suffix
+ luaname = filename -- forced suffix
lucname = nil
end
-- when not overloaded by explicit suffix we look for a luc file first
@@ -136,7 +137,7 @@ function environment.loadluafile(filename, version)
chunk = loadfile(fullname) -- this way we don't need a file exists check
end
if chunk then
- assert(chunk)()
+ chunk()
if version then
-- we check of the version number of this chunk matches
local v = version -- can be nil
@@ -168,9 +169,24 @@ function environment.loadluafile(filename, version)
report_lua("unknown file %a",filename)
end
else
- assert(chunk)()
+ chunk()
return true
end
end
return false
end
+
+environment.filenames = setmetatable( { }, {
+ __index = function(t,k)
+ local v = environment.files[k]
+ if v then
+ return (gsub(v,"%.+$",""))
+ end
+ end,
+ __newindex = function(t,k)
+ -- nothing
+ end,
+ __len = function(t)
+ return #environment.files
+ end,
+} )
diff --git a/tex/context/base/mkiv/luat-fio.lua b/tex/context/base/mkiv/luat-fio.lua
index 806caefe6..2996ae66a 100644
--- a/tex/context/base/mkiv/luat-fio.lua
+++ b/tex/context/base/mkiv/luat-fio.lua
@@ -70,12 +70,16 @@ if not resolvers.initialized() then
return okay or ""
end
+ resolvers.findpk = findpk
+
-- register('process_jobname' , function(name) return name end, true)
register('find_read_file' , function(id,name) return findtexfile(name) end, true)
register('open_read_file' , function( name) return opentexfile(name) end, true)
register('find_data_file' , function(name) return findbinfile(name,"tex") end, true)
+ register('open_data_file' , function(name) return opentexfile(name) end, true)
+
register('find_enc_file' , function(name) return findbinfile(name,"enc") end, true)
register('find_font_file' , function(name) return findbinfile(name,"tfm") end, true)
-- register('find_format_file' , function(name) return findbinfile(name,"fmt") end, true)
diff --git a/tex/context/base/mkiv/luat-fmt.lua b/tex/context/base/mkiv/luat-fmt.lua
index 30c55eecc..1c9222d95 100644
--- a/tex/context/base/mkiv/luat-fmt.lua
+++ b/tex/context/base/mkiv/luat-fmt.lua
@@ -19,9 +19,9 @@ local function primaryflags()
if arguments.silent then
flags[#flags+1] = "--interaction=batchmode"
end
- if arguments.jit then
- flags[#flags+1] = "--jiton"
- end
+ -- if arguments.jit then
+ -- flags[#flags+1] = "--jiton"
+ -- end
return concat(flags," ")
end
@@ -48,10 +48,16 @@ local function secondaryflags()
if arguments.ansi then
flags[#flags+1] = "--c:ansi"
end
+ if arguments.strip then
+ flags[#flags+1] = "--c:strip"
+ end
+ if arguments.lmtx then
+ flags[#flags+1] = "--c:lmtx"
+ end
return concat(flags," ")
end
--- The silent option is Taco. It's a bit of a hack because we cannot yet mess
+-- The silent option is for Taco. It's a bit of a hack because we cannot yet mess
-- with directives. In fact, I could probably clean up the maker a bit by now.
local template = [[--ini %primaryflags% --lua=%luafile% %texfile% %secondaryflags% %dump% %redirect%]]
diff --git a/tex/context/base/mkiv/luat-ini.lua b/tex/context/base/mkiv/luat-ini.lua
index de7254922..ffd402c77 100644
--- a/tex/context/base/mkiv/luat-ini.lua
+++ b/tex/context/base/mkiv/luat-ini.lua
@@ -25,15 +25,19 @@ if not global then
global = _G
end
-LUATEXVERSION = status.luatex_version/100
- + tonumber(status.luatex_revision)/1000
+LUATEXVERSION = status.luatex_version/100
+ + tonumber(status.luatex_revision)/1000
-LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine)
- or (string.find(status.banner,"LuajitTeX",1,true) and "luajittex" or "luatex")
+LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine)
+ or (string.find(status.banner,"LuajitTeX",1,true) and "luajittex" or "luatex")
-JITSUPPORTED = LUATEXENGINE == "luajittex" or jit
+LUATEXFUNCTIONALITY = status.development_id or 6346
-INITEXMODE = status.ini_version
+JITSUPPORTED = LUATEXENGINE == "luajittex" or jit
+
+INITEXMODE = status.ini_version
+
+CONTEXTLMTXMODE = CONTEXTLMTXMODE or (status.obj_ptr == nil and 2 or 1)
function os.setlocale()
-- no need for a message
diff --git a/tex/context/base/mkiv/luat-ini.mkiv b/tex/context/base/mkiv/luat-ini.mkiv
index 872d27e77..da5a3a310 100644
--- a/tex/context/base/mkiv/luat-ini.mkiv
+++ b/tex/context/base/mkiv/luat-ini.mkiv
@@ -265,55 +265,84 @@
% \def\syst_helpers_checked_stripped_csname#1%
% {\if\noexpand#1\letterbackslash\else#1\fi}
-\normalprotected\def\installctxfunction#1#2% expandable
- {\edef\m_syst_name{\csstring#1}%
- \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax
- \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}}
-
-\normalprotected\def\installctxscanner#1#2% expandable
- {\edef\m_syst_name{\csstring#1}%
- \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax
- \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}}
-
-\normalprotected\def\installprotectedctxfunction#1#2% protected
- {\edef\m_syst_name{\csstring#1}%
- \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax
- \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}}
-
-\normalprotected\def\installprotectedctxscanner#1#2% protected
- {\edef\m_syst_name{\csstring#1}%
- \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax
- \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}}
-
-% not yet used
-
-\ifdefined\luafunctioncall \else
- \protected\def\luafunctioncall{\luafunctioncall}
-\fi
+\ifdefined\normalluadef
+
+ \normalprotected\def\installctxfunction#1#2% expandable
+ {\edef\m_syst_name{\csstring#1}%
+ \global\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax}
+
+ \normalprotected\def\installctxscanner#1#2% expandable
+ {\edef\m_syst_name{\csstring#1}%
+ \global\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax}
+
+ \normalprotected\def\installprotectedctxfunction#1#2% protected
+ {\edef\m_syst_name{\csstring#1}%
+ \global\normalprotected\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax}
+
+ \normalprotected\def\installprotectedctxscanner#1#2% protected
+ {\edef\m_syst_name{\csstring#1}%
+ \global\normalprotected\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax}
+
+ \normalprotected\def\resetctxscanner#1%
+ {\edef\m_syst_name{\csstring#1}%
+ \expandafter\glet\csname\m_syst_name\endcsname\relax}
+
+ % \let\installctxfunctioncall \installctxfunction
+ % \let\installctxscannercall \installctxscanner
+ % \let\installprotectedctxfunctioncall\installprotectedctxfunction
+ % \let\installprotectedctxscannercall \installprotectedctxscanner
+
+\else
+
+ \ifdefined\luafunctioncall \else
+ \normalprotected\def\luafunctioncall{\luafunction}
+ \fi
+
+ \normalprotected\def\installctxfunction#1#2% expandable
+ {\edef\m_syst_name{\csstring#1}%
+ \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax
+ \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}}
+
+ \normalprotected\def\installctxscanner#1#2% expandable
+ {\edef\m_syst_name{\csstring#1}%
+ \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax
+ \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunction\csname\??luafunction\m_syst_name\endcsname}}
+
+ \normalprotected\def\installprotectedctxfunction#1#2% protected
+ {\edef\m_syst_name{\csstring#1}%
+ \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax
+ \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}}
+
+ \normalprotected\def\installprotectedctxscanner#1#2% protected
+ {\edef\m_syst_name{\csstring#1}%
+ \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax
+ \expandafter\xdef\csname\m_syst_name\endcsname{\noexpand\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}}
+
+ \normalprotected\def\resetctxscanner#1%
+ {\edef\m_syst_name{\csstring#1}%
+ \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\zerocount
+ \expandafter\glet\csname\m_syst_name\endcsname\relax}
+
+ % \normalprotected\def\installctxfunctioncall#1#2%
+ % {\edef\m_syst_name{\csstring#1}%
+ % \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax
+ % \expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}}
+ %
+ % \normalprotected\def\installctxscannercall#1#2%
+ % {\edef\m_syst_name{\csstring#1}%
+ % \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax
+ % \expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}}
+ %
+ % \normalprotected\def\installprotectedctxfunctioncall#1#2%
+ % {\edef\m_syst_name{\csstring#1}%
+ % \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax
+ % \normalprotected\expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}}
+ %
+ % \normalprotected\def\installprotectedctxscannercall#1#2%
+ % {\edef\m_syst_name{\csstring#1}%
+ % \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax
+ % \normalprotected\expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}}
-\normalprotected\def\installctxfunctioncall#1#2%
- {\edef\m_syst_name{\csstring#1}%
- \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax
- \expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}}
-
-\normalprotected\def\installctxscannercall#1#2%
- {\edef\m_syst_name{\csstring#1}%
- \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax
- \expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}}
-
-\normalprotected\def\installprotectedctxfunctioncall#1#2%
- {\edef\m_syst_name{\csstring#1}%
- \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxfunction("#2",true)}\relax
- \normalprotected\expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}}
-
-\normalprotected\def\installprotectedctxscannercall#1#2%
- {\edef\m_syst_name{\csstring#1}%
- \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name","#2",true)}\relax
- \normalprotected\expandafter\xdef\csname\m_syst_name\endcsname{\luafunctioncall\csname\??luafunction\m_syst_name\endcsname}}
-
-\normalprotected\def\resetctxscanner#1%
- {\edef\m_syst_name{\csstring#1}%
- \global\expandafter\chardef\csname\??luafunction\m_syst_name\endcsname\zerocount
- \global\expandafter\let\csname\m_syst_name\endcsname\relax}
+\fi
\protect \endinput
diff --git a/tex/context/base/mkiv/luat-lib.mkiv b/tex/context/base/mkiv/luat-lib.mkiv
index 0df31a4e5..d5f6099ca 100644
--- a/tex/context/base/mkiv/luat-lib.mkiv
+++ b/tex/context/base/mkiv/luat-lib.mkiv
@@ -19,7 +19,7 @@
\registerctxluafile{util-sac}{optimize}
\registerctxluafile{util-sto}{} % could also be done in trac-deb.mkiv
\registerctxluafile{util-pck}{}
-\registerctxluafile{util-seq}{}
+% \registerctxluafile{util-seq}{}
%registerctxluafile{util-mrg}{} % not needed in context itself, only mtxrun
%registerctxluafile{util-lua}{} % moved
\registerctxluafile{util-prs}{}
@@ -35,11 +35,25 @@
\registerctxluafile{util-deb}{} % could also be done in trac-deb.mkiv
\registerctxluafile{util-tpl}{} % needs tracker
+\registerctxluafile{util-seq}{}
\registerctxluafile{util-sta}{}
\registerctxluafile{util-sbx}{} % needs tracker and templates
+\registerctxluafile{util-soc-imp-reset} {}
+\registerctxluafile{util-soc-imp-socket} {}
+%registerctxluafile{util-soc-imp-copas} {}
+\registerctxluafile{util-soc-imp-ltn12} {}
+%registerctxluafile{util-soc-imp-mbox} {}
+\registerctxluafile{util-soc-imp-mime} {}
+\registerctxluafile{util-soc-imp-url} {}
+\registerctxluafile{util-soc-imp-headers}{}
+\registerctxluafile{util-soc-imp-http} {}
+\registerctxluafile{util-soc-imp-tp} {}
+%registerctxluafile{util-soc-imp-ftp} {}
+%registerctxluafile{util-soc-imp-smtp} {}
+
\registerctxluafile{data-ini}{}
\registerctxluafile{data-exp}{}
\registerctxluafile{data-env}{}
diff --git a/tex/context/base/mkiv/luat-run.lua b/tex/context/base/mkiv/luat-run.lua
index 59fb0b937..98f981777 100644
--- a/tex/context/base/mkiv/luat-run.lua
+++ b/tex/context/base/mkiv/luat-run.lua
@@ -115,6 +115,29 @@ local function wrapup_synctex()
synctex.wrapup()
end
+-- For Taco ...
+
+local sequencers = utilities.sequencers
+local appendgroup = sequencers.appendgroup
+local appendaction = sequencers.appendaction
+local wrapupactions = sequencers.new { }
+
+appendgroup(wrapupactions,"system")
+appendgroup(wrapupactions,"user")
+
+local function wrapup_run()
+ local runner = wrapupactions.runner
+ if runner then
+ runner()
+ end
+end
+
+function luatex.wrapup(action)
+ appendaction(wrapupactions,"user",action)
+end
+
+appendaction(wrapupactions,"system",synctex.wrapup)
+
-- this can be done later
callbacks.register('start_run', start_run, "actions performed at the beginning of a run")
@@ -126,20 +149,26 @@ callbacks.register('stop_run', stop_run, "actions perf
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")
-callbacks.register('start_page_number', start_shipout_page, "actions performed at the beginning of a shipout")
-callbacks.register('stop_page_number', stop_shipout_page, "actions performed at the end of a shipout")
+---------.register('start_page_number', start_shipout_page, "actions performed at the beginning of a shipout")
+---------.register('stop_page_number', stop_shipout_page, "actions performed at the end of a shipout")
+
+callbacks.register('start_page_number', function() end, "actions performed at the beginning of a shipout")
+callbacks.register('stop_page_number', function() end, "actions performed at the end of a shipout")
callbacks.register('process_input_buffer', false, "actions performed when reading data")
callbacks.register('process_output_buffer', false, "actions performed when writing data")
callbacks.register("pre_dump", pre_dump_actions, "lua related finalizers called before we dump the format") -- comes after \everydump
-if LUATEXFUNCTIONALITY and LUATEXFUNCTIONALITY > 6505 then
- callbacks.register("finish_synctex", wrapup_synctex, "rename temporary synctex file")
- callbacks.register('wrapup_run', false, "actions performed after closing files")
-else
- callbacks.register("finish_synctex_callback", wrapup_synctex, "rename temporary synctex file")
-end
+-- finish_synctex might go away (move to wrapup_run)
+
+callbacks.register("finish_synctex", wrapup_synctex, "rename temporary synctex file")
+callbacks.register('wrapup_run', wrapup_run, "actions performed after closing files")
+
+-- temp hack for testing:
+
+callbacks.functions.start_page_number = start_shipout_page
+callbacks.functions.stop_page_number = stop_shipout_page
-- an example:
@@ -176,14 +205,6 @@ luatex.registerstopactions(luatex.cleanuptempfiles)
-- filenames
-local types = {
- "data",
- "font map",
- "image",
- "font subset",
- "full font",
-}
-
local report_open = logs.reporter("open source")
local report_close = logs.reporter("close source")
local report_load = logs.reporter("load resource")
@@ -199,15 +220,8 @@ function luatex.currentfile()
return stack[#stack] or tex.jobname
end
-local function report_start(left,name)
- if not left then
- -- skip
- elseif left ~= 1 then
- if all then
- -- report_load("%s > %s",types[left],name or "?")
- report_load("type %a, name %a",types[left],name or "?")
- end
- elseif find(name,"virtual://",1,true) then
+local function report_start(name)
+ if find(name,"virtual://",1,true) then
insert(stack,false)
else
insert(stack,name)
@@ -219,16 +233,47 @@ local function report_start(left,name)
end
end
-local function report_stop(right)
- if level == 1 or not right or right == 1 then
- local name = remove(stack)
- if name then
- -- report_close("%i > %i > %s",level,total,name or "?")
- report_close("level %i, order %i, name %a",level,total,name or "?")
- level = level - 1
- synctex.setfilename(stack[#stack] or tex.jobname)
+local function report_stop()
+ local name = remove(stack)
+ if name then
+ -- report_close("%i > %i > %s",level,total,name or "?")
+ report_close("level %i, order %i, name %a",level,total,name or "?")
+ level = level - 1
+ synctex.setfilename(stack[#stack] or tex.jobname)
+ end
+end
+
+if CONTEXTLMTXMODE < 2 then
+
+ local types = {
+ "data",
+ "font map",
+ "image",
+ "font subset",
+ "full font",
+ }
+
+ local do_report_start = report_start
+ local do_report_stop = report_stop
+
+ report_start = function(left,name)
+ if not left then
+ -- skip
+ elseif left ~= 1 then
+ if all then
+ report_load("type %a, name %a",types[left],name or "?")
+ end
+ else
+ do_report_start(name)
+ end
+ end
+
+ report_stop = function(right)
+ if level == 1 or not right or right == 1 then
+ do_report_stop()
end
end
+
end
local function report_none()
diff --git a/tex/context/base/mkiv/luat-soc.lua b/tex/context/base/mkiv/luat-soc.lua
deleted file mode 100644
index 9342a4b33..000000000
--- a/tex/context/base/mkiv/luat-soc.lua
+++ /dev/null
@@ -1,11 +0,0 @@
--- 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"
-
--- "luatex/lua/socket/smtp.lua"
diff --git a/tex/context/base/mkiv/luat-soc.mkiv b/tex/context/base/mkiv/luat-soc.mkiv
new file mode 100644
index 000000000..b2ce70483
--- /dev/null
+++ b/tex/context/base/mkiv/luat-soc.mkiv
@@ -0,0 +1,52 @@
+%D \module
+%D [ file=luat-soc,
+%D version=2018.08.05,
+%D title=\CONTEXT\ Lua Macros,
+%D subtitle=Socket Libraries,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Lua Macros / Socket Libraries}
+
+%D In \LUATEX\ we provide the socket library that is more or less the standard one
+%D for \LUA. It has been around for a while and seems to be pretty stable. The
+%D binary module is copmpiled into \LUATEX\ and the accompanying .lua files are
+%D preloaded. These files are mostly written by Diego Nehab, Andre Carregal, Javier
+%D Guerra, and Fabio Mascarenhas with contributions from Diego Nehab, Mike Pall,
+%D David Burgess, Leonardo Godinho, Thomas Harning Jr., and Gary NG. The originals
+%D are part of and copyrighted by the Kepler project.
+%D
+%D Here we reload a slightly reworked version of these \type {.lua} files. We keep
+%D the same (documented) interface but streamlined some fo the code. No more
+%D modules, no more pre 5.2 \LUA, etc. Also, as it loads into the \CONTEXT
+%D ecosystem, we plug in some logging. (and maybe tracing in the future). As we
+%D don't support serial ports in \LUATEX, related code has been dropped.
+%D
+%D The files are reformatted so that we can more easilly add additional features
+%D and|/|or tracing options. Any error introduced there is our fault! The url module
+%D might be replaced by the one in \CONTEXT. When we need mbox a suitable variant
+%D will be provided.
+
+%D Currently we preload the related \LUA\ code in \LUATEX, but that might change at
+%D some point. We're prepared for that.
+
+% \registerctxluafile{util-soc-imp-reset} {}
+%
+% \registerctxluafile{util-soc-imp-socket} {}
+% % registerctxluafile{util-soc-imp-copas} {}
+% \registerctxluafile{util-soc-imp-ltn12} {}
+% % registerctxluafile{util-soc-imp-mbox} {}
+% \registerctxluafile{util-soc-imp-mime} {}
+% \registerctxluafile{util-soc-imp-url} {}
+% \registerctxluafile{util-soc-imp-headers}{}
+% \registerctxluafile{util-soc-imp-http} {}
+% \registerctxluafile{util-soc-imp-tp} {}
+% % registerctxluafile{util-soc-imp-ftp} {}
+% % registerctxluafile{util-soc-imp-smtp} {}
+
+\endinput
diff --git a/tex/context/base/mkiv/luat-sto.lua b/tex/context/base/mkiv/luat-sto.lua
index e67830b0d..ce891765a 100644
--- a/tex/context/base/mkiv/luat-sto.lua
+++ b/tex/context/base/mkiv/luat-sto.lua
@@ -78,7 +78,7 @@ if environment.initex then
dumped = concat({ definition, comment, dumped },"\n")
local code = nil
local name = formatters["slot %s (%s)"](max,name)
- if LUAVERSION >= 5.3 and LUATEXFUNCTIONALITY >= 6454 then
+ if LUAVERSION >= 5.3 then
local code = loadstring(dumped,name)
setbytecode(max,code,strip)
else
diff --git a/tex/context/base/mkiv/luat-usr.lua b/tex/context/base/mkiv/luat-usr.lua
index ebcb0f0e8..b49379bbf 100644
--- a/tex/context/base/mkiv/luat-usr.lua
+++ b/tex/context/base/mkiv/luat-usr.lua
@@ -26,8 +26,6 @@ local io = io
local os = os
local lpeg = lpeg
-local luanames = lua.name -- luatex itself
-
local setmetatableindex = table.setmetatableindex
local load = load
local xpcall = xpcall
@@ -135,7 +133,6 @@ local function registername(name,message)
messages[lnn] = message
numbers[name] = lnn
end
- luanames[lnn] = instance_banner(message)
local report = reporter("lua instance",message)
local proxy = {
-- we can access all via:
diff --git a/tex/context/base/mkiv/luat-usr.mkiv b/tex/context/base/mkiv/luat-usr.mkiv
index 760de9f21..f3868ccf4 100644
--- a/tex/context/base/mkiv/luat-usr.mkiv
+++ b/tex/context/base/mkiv/luat-usr.mkiv
@@ -69,7 +69,7 @@
\obeyluatokens
\csname\??luacode#1\endcsname}%
%
- \global\expandafter\let\csname\s!stop#1\s!code\endcsname\relax
+ \expandafter\glet\csname\s!stop#1\s!code\endcsname\relax
%
\normalexpanded{\xdef\csname\??luacode#1\endcsname##1\csname\s!stop#1\s!code\endcsname}%
{\noexpand\expandafter\endgroup
@@ -77,7 +77,7 @@
\expandafter\noexpand\csname clf_\fullname\endcsname
\noexpand\expandafter{\noexpand\normalexpanded{##1}}}%
%
- \global\expandafter\let\csname#1\s!code\expandafter\endcsname\csname clf_\fullname\endcsname
+ \expandafter\glet\csname#1\s!code\expandafter\endcsname\csname clf_\fullname\endcsname
\fi
\fi
\egroup}
diff --git a/tex/context/base/mkiv/lxml-aux.lua b/tex/context/base/mkiv/lxml-aux.lua
index 78cf1d6bd..ed0f03fd8 100644
--- a/tex/context/base/mkiv/lxml-aux.lua
+++ b/tex/context/base/mkiv/lxml-aux.lua
@@ -134,10 +134,12 @@ end
function xml.collect_tags(root, pattern, nonamespace)
local collected = xmlapplylpath(root,pattern)
if collected then
- local t, n = { }, 0
+ local t = { }
+ local n = 0
for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
+ local e = collected[c]
+ local ns = e.ns
+ local tg = e.tg
n = n + 1
if nonamespace then
t[n] = tg
@@ -226,7 +228,7 @@ function xml.delete(root,pattern)
if trace_manipulations then
report('deleting',pattern,c,e)
end
- local d = p.dt
+ local d = p.dt
local ni = e.ni
if ni <= #d then
if false then
@@ -313,8 +315,10 @@ local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
local function inject_e(e)
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
+ local r = e.__p__
+ local d = r.dt
+ local k = e.ni
+ local rri = r.ri
local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
if edt then
local be, af
@@ -354,7 +358,8 @@ local function insert_element(root,pattern,whatever,before) -- todo: element als
local collected = element and xmlapplylpath(root,pattern)
local function insert_e(e)
local r = e.__p__
- local d, k = r.dt, e.ni
+ local d = r.dt
+ local k = e.ni
if not before then
k = k + 1
end
@@ -860,8 +865,10 @@ function xml.separate(x,pattern)
report_xml("warning: xml.separate changes root")
x = d
end
- local t, n = { "\n" }, 1
- local i, nd = 1, #d
+ local t = { "\n" }
+ local n = 1
+ local i = 1
+ local nd = #d
while i <= nd do
while i <= nd do
local di = d[i]
diff --git a/tex/context/base/mkiv/lxml-css.lua b/tex/context/base/mkiv/lxml-css.lua
index 1787c53df..b0f5c9b72 100644
--- a/tex/context/base/mkiv/lxml-css.lua
+++ b/tex/context/base/mkiv/lxml-css.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['lxml-css'] = {
license = "see context related readme files"
}
-local tonumber, rawset, type = tonumber, rawset, type
+local tonumber, rawset, type, select = tonumber, rawset, type, select
local lower, format, find, gmatch = string.lower, string.format, string.find, string.gmatch
local topattern, is_empty = string.topattern, string.is_empty
local P, S, C, R, Cb, Cg, Carg, Ct, Cc, Cf, Cs = lpeg.P, lpeg.S, lpeg.C, lpeg.R, lpeg.Cb, lpeg.Cg, lpeg.Carg, lpeg.Ct, lpeg.Cc, lpeg.Cf, lpeg.Cs
@@ -118,24 +118,33 @@ css.padding = padding
-- print(padding("0",pixel,hsize,exheight,emwidth))
--- local currentfont = font.current
--- local texget = tex.get
--- local hashes = fonts.hashes
--- local quads = hashes.quads
--- local xheights = hashes.xheights
---
--- local function padding(str)
--- local font = currentfont()
--- local exheight = xheights[font]
--- local emwidth = quads[font]
--- local hsize = texget("hsize")/100
--- local pixel = emwidth/100
--- return padding(str,pixel,hsize,exheight,emwidth)
--- end
---
--- function css.simplepadding(str)
--- context("%ssp",padding(str,pixel,hsize,exheight,emwidth))
--- end
+local context = context
+
+if context then
+
+ local currentfont = font.current
+ local texget = tex.get
+ local hashes = fonts.hashes
+ local quads = hashes.quads
+ local xheights = hashes.xheights
+
+ local function todimension(str)
+ local font = currentfont()
+ local exheight = xheights[font]
+ local emwidth = quads[font]
+ local hsize = texget("hsize")/100
+ local pixel = emwidth/100
+ return dimension(str,pixel,hsize,exheight,emwidth)
+ end
+
+ css.todimension = todimension
+
+ function context.cssdimension(str)
+ -- context("%ssp",todimension(str))
+ context(todimension(str) .. "sp")
+ end
+
+end
local pattern = Cf( Ct("") * (
Cg(
@@ -949,7 +958,7 @@ local someaction = skipspace * colon * skipspace * (somevalue/ctx_sprint)
-- -- cache patterns (2.13):
-local patterns= setmetatableindex(function(t,k)
+local patterns = setmetatableindex(function(t,k)
local v = P(k * someaction + 1)^0
t[k] = v
return v
@@ -993,3 +1002,91 @@ interfaces.implement {
actions = css.mappedstylevalue,
arguments = "3 strings",
}
+
+-- more (for mm)
+
+local containsws = string.containsws
+local classsplitter = lpeg.tsplitat(whitespace^1)
+
+function xml.functions.classes(e,class) -- cache
+ if class then
+ local at = e.at
+ local data = at[class] or at.class
+ if data then
+ return lpegmatch(classsplitter,data) or { }
+ end
+ end
+ return { }
+end
+
+-- function xml.functions.hasclass(e,class,name)
+-- if class then
+-- local at = e.at
+-- local data = at[class] or at.class
+-- if data then
+-- return data == name or containsws(data,name)
+-- end
+-- end
+-- return false
+-- end
+--
+-- function xml.expressions.hasclass(attribute,name)
+-- if attribute then
+-- return attribute == name or containsws(attribute,name)
+-- end
+-- return false
+-- end
+
+function xml.functions.hasclass(e,class,name,more,...)
+ if class and name then
+ local at = e.at
+ local data = at[class] or at.class
+ if not data or data == "" then
+ return false
+ end
+ if data == name or data == more then
+ return true
+ end
+ if containsws(data,name) then
+ return true
+ end
+ if not more then
+ return false
+ end
+ if containsws(data,more) then
+ return true
+ end
+ for i=1,select("#",...) do
+ if containsws(data,select(i,...)) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
+function xml.expressions.hasclass(data,name,more,...)
+ if data then
+ if not data or data == "" then
+ return false
+ end
+ if data == name or data == more then
+ return true
+ end
+ if containsws(data,name) then
+ return true
+ end
+ if not more then
+ return false
+ end
+ if containsws(data,more) then
+ return true
+ end
+ for i=1,select("#",...) do
+ if containsws(data,select(i,...)) then
+ return true
+ end
+ end
+ end
+ return false
+end
diff --git a/tex/context/base/mkiv/lxml-inf.lua b/tex/context/base/mkiv/lxml-inf.lua
index 8d99d6270..6fb64c0fe 100644
--- a/tex/context/base/mkiv/lxml-inf.lua
+++ b/tex/context/base/mkiv/lxml-inf.lua
@@ -17,7 +17,8 @@ local getid = lxml.getid
local status, stack
local function get(e,d)
- local ns, tg = e.ns, e.tg
+ local ns = e.ns
+ local tg = e.tg
local name = tg
if ns ~= "" then name = ns .. ":" .. tg end
stack[d] = name
diff --git a/tex/context/base/mkiv/lxml-ini.mkiv b/tex/context/base/mkiv/lxml-ini.mkiv
index 7c97ffb2c..5cb4bb22d 100644
--- a/tex/context/base/mkiv/lxml-ini.mkiv
+++ b/tex/context/base/mkiv/lxml-ini.mkiv
@@ -36,11 +36,11 @@
% for now indirect
-\def\xmlconcat #1#2#3{\clf_xmlconcat {#1}{#2}{\detokenize{#3}}}
-\def\xmlconcatrange #1#2#3#4#5{\clf_xmlconcatrange {#1}{#2}{#3}{#4}{\detokenize{#5}}}
-\def\xmlload #1#2{\clf_xmlload {#1}{#2}{\directxmlparameter\c!compress}}
-\def\xmlloadbuffer #1#2{\clf_xmlloadbuffer {#1}{#2}{\directxmlparameter\c!compress}}
-\def\xmlloaddata #1#2{\clf_xmlloaddata {#1}{#2}{\directxmlparameter\c!compress}}
+\def\xmlconcat #1#2#3{\clf_xmlconcat {#1}{#2}{\detokenize{#3}}}
+\def\xmlconcatrange #1#2#3#4#5{\clf_xmlconcatrange{#1}{#2}{#3}{#4}{\detokenize{#5}}}
+\def\xmlload #1#2{\clf_xmlload {#1}{#2}{\directxmlparameter\c!compress}}
+\def\xmlloadbuffer #1#2{\clf_xmlloadbuffer {#1}{#2}{\directxmlparameter\c!compress}}
+\def\xmlloaddata #1#2{\clf_xmlloaddata {#1}{#2}{\directxmlparameter\c!compress}}
% aliased
@@ -231,6 +231,7 @@
\unexpanded\def\xmlremovedocumentsetup #1#2{\clf_xmlremovesetup {#1}{#2}}
\unexpanded\def\xmlresetdocumentsetups #1{\clf_xmlresetsetups {#1}}
+\unexpanded\def\xmlflushsetups #1{\clf_xmlflushsetups {#1}{*}{}} % #1 == id where to apply *
\unexpanded\def\xmlflushdocumentsetups #1#2{\clf_xmlflushsetups {#1}{*}{#2}} % #1 == id where to apply * and #2
\let\xmlregistersetup \xmlappendsetup
@@ -240,7 +241,7 @@
\unexpanded\def\xmlregisteredsetups
{\xmlstarttiming
- \xmlflushsetups
+ \xmlflushsetups\xmldocument
\xmldefaulttotext\xmldocument % after include
\xmlstoptiming}
@@ -260,8 +261,8 @@
%xmlpushdocument{#3}%
#2{#3}{#4}%
\setcatcodetable\notcatcodes
- \doifelsenothing{#5}
- {\xmlsetup{#3}{xml:process}}
+ \doifelsenothing{#5}%
+ {\xmlsetup{#3}{xml:process}}%
{\xmlsetup{#3}{#5}}%
%xmlpopdocument
\endgroup}
@@ -326,7 +327,7 @@
\fi
\unexpanded\def\stopxmldisplayverbatim
{\endofverbatimlines
- \stoppacked}
+ \stoppacked}%
\doinitializeverbatim
\beginofverbatimlines}
@@ -404,7 +405,7 @@
\c!entities=\v!no] % load big entity file
\appendtoks
- \doif{\directxmlparameter\c!entities}\clf_xmlloadentities
+ \doif{\directxmlparameter\c!entities}\v!yes\clf_xmlloadentities
\to \everysetupxml
\def\xmlmapvalue #1#2#3{\setvalue{\??xmlmapvalue#1:#2}{#3}} % keep #3 to grab spaces
diff --git a/tex/context/base/mkiv/lxml-lpt.lua b/tex/context/base/mkiv/lxml-lpt.lua
index bb6fb4568..392c1a401 100644
--- a/tex/context/base/mkiv/lxml-lpt.lua
+++ b/tex/context/base/mkiv/lxml-lpt.lua
@@ -157,32 +157,47 @@ apply_axis['root'] = function(list)
end
apply_axis['self'] = function(list)
---~ local collected = { }
---~ for l=1,#list do
---~ collected[l] = list[l]
---~ end
---~ return collected
+ -- local collected = { }
+ -- for l=1,#list do
+ -- collected[l] = list[l]
+ -- end
+ -- return collected
return list
end
apply_axis['child'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
local dt = ll.dt
if dt then -- weird that this is needed
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
+ local n = #dt
+ if n == 0 then
+ ll.en = 0
+ elseif n == 1 then
+ local dk = dt[1]
if dk.tg then
c = c + 1
collected[c] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ dk.ni = 1 -- refresh
+ dk.ei = 1
+ ll.en = 1
end
+ else
+ local en = 0
+ for k=1,#dt do
+ local dk = dt[k]
+ if dk.tg then
+ c = c + 1
+ en = en + 1
+ collected[c] = dk
+ dk.ni = k -- refresh
+ dk.ei = en
+ end
+ end
+ ll.en = en
end
- ll.en = en
end
end
return collected
@@ -191,25 +206,43 @@ end
local function collect(list,collected,c)
local dt = list.dt
if dt then
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
+ local n = #dt
+ if n == 0 then
+ list.en = 0
+ elseif n == 1 then
+ local dk = dt[1]
if dk.tg then
c = c + 1
collected[c] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ dk.ni = 1 -- refresh
+ dk.ei = 1
c = collect(dk,collected,c)
+ list.en = 1
+ else
+ list.en = 0
end
+ else
+ local en = 0
+ for k=1,n do
+ local dk = dt[k]
+ if dk.tg then
+ c = c + 1
+ en = en + 1
+ collected[c] = dk
+ dk.ni = k -- refresh
+ dk.ei = en
+ c = collect(dk,collected,c)
+ end
+ end
+ list.en = en
end
- list.en = en
end
return c
end
apply_axis['descendant'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
c = collect(list[l],collected,c)
end
@@ -219,24 +252,41 @@ end
local function collect(list,collected,c)
local dt = list.dt
if dt then
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
+ local n = #dt
+ if n == 0 then
+ list.en = 0
+ elseif n == 1 then
+ local dk = dt[1]
if dk.tg then
c = c + 1
collected[c] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ dk.ni = 1 -- refresh
+ dk.ei = 1
c = collect(dk,collected,c)
+ list.en = 1
end
+ else
+ local en = 0
+ for k=1,#dt do
+ local dk = dt[k]
+ if dk.tg then
+ c = c + 1
+ en = en + 1
+ collected[c] = dk
+ dk.ni = k -- refresh
+ dk.ei = en
+ c = collect(dk,collected,c)
+ end
+ end
+ list.en = en
end
- list.en = en
end
return c
end
+
apply_axis['descendant-or-self'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
if ll.special ~= true then -- catch double root
@@ -249,7 +299,8 @@ apply_axis['descendant-or-self'] = function(list)
end
apply_axis['ancestor'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
while ll do
@@ -264,7 +315,8 @@ apply_axis['ancestor'] = function(list)
end
apply_axis['ancestor-or-self'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
c = c + 1
@@ -281,7 +333,8 @@ apply_axis['ancestor-or-self'] = function(list)
end
apply_axis['parent'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local pl = list[l].__p__
if pl then
@@ -301,45 +354,47 @@ apply_axis['namespace'] = function(list)
end
apply_axis['following'] = function(list) -- incomplete
---~ local collected, c = { }, 0
---~ for l=1,#list do
---~ local ll = list[l]
---~ local p = ll.__p__
---~ local d = p.dt
---~ for i=ll.ni+1,#d do
---~ local di = d[i]
---~ if type(di) == "table" then
---~ c = c + 1
---~ collected[c] = di
---~ break
---~ end
---~ end
---~ end
---~ return collected
+ -- local collected, c = { }, 0
+ -- for l=1,#list do
+ -- local ll = list[l]
+ -- local p = ll.__p__
+ -- local d = p.dt
+ -- for i=ll.ni+1,#d do
+ -- local di = d[i]
+ -- if type(di) == "table" then
+ -- c = c + 1
+ -- collected[c] = di
+ -- break
+ -- end
+ -- end
+ -- end
+ -- return collected
return { }
end
apply_axis['preceding'] = function(list) -- incomplete
---~ local collected, c = { }, 0
---~ for l=1,#list do
---~ local ll = list[l]
---~ local p = ll.__p__
---~ local d = p.dt
---~ for i=ll.ni-1,1,-1 do
---~ local di = d[i]
---~ if type(di) == "table" then
---~ c = c + 1
---~ collected[c] = di
---~ break
---~ end
---~ end
---~ end
---~ return collected
+ -- local collected = { }
+ -- local c = 0
+ -- for l=1,#list do
+ -- local ll = list[l]
+ -- local p = ll.__p__
+ -- local d = p.dt
+ -- for i=ll.ni-1,1,-1 do
+ -- local di = d[i]
+ -- if type(di) == "table" then
+ -- c = c + 1
+ -- collected[c] = di
+ -- break
+ -- end
+ -- end
+ -- end
+ -- return collected
return { }
end
apply_axis['following-sibling'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -356,7 +411,8 @@ apply_axis['following-sibling'] = function(list)
end
apply_axis['preceding-sibling'] = function(list)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -373,7 +429,8 @@ apply_axis['preceding-sibling'] = function(list)
end
apply_axis['reverse-sibling'] = function(list) -- reverse preceding
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
for l=1,#list do
local ll = list[l]
local p = ll.__p__
@@ -400,7 +457,8 @@ local function apply_nodes(list,directive,nodes)
-- ... currently ignored
local maxn = #nodes
if maxn == 3 then --optimized loop
- local nns, ntg = nodes[2], nodes[3]
+ local nns = nodes[2]
+ local ntg = nodes[3]
if not nns and not ntg then -- wildcard
if directive then
return list
@@ -408,40 +466,47 @@ local function apply_nodes(list,directive,nodes)
return { }
end
else
- local collected, c, m, p = { }, 0, 0, nil
+ local collected = { }
+ local c = 0
+ local m = 0
+ local p = nil
if not nns then -- only check tag
for l=1,#list do
- local ll = list[l]
+ local ll = list[l]
local ltg = ll.tg
if ltg then
if directive then
if ntg == ltg then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
elseif ntg ~= ltg then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
end
end
elseif not ntg then -- only check namespace
for l=1,#list do
- local ll = list[l]
+ local ll = list[l]
local lns = ll.rn or ll.ns
if lns then
if directive then
if lns == nns then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
elseif lns ~= nns then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
end
end
@@ -454,14 +519,16 @@ local function apply_nodes(list,directive,nodes)
local ok = ltg == ntg and lns == nns
if directive then
if ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
elseif not ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
end
end
@@ -469,15 +536,19 @@ local function apply_nodes(list,directive,nodes)
return collected
end
else
- local collected, c, m, p = { }, 0, 0, nil
+ local collected = { }
+ local c = 0
+ local m = 0
+ local p = nil
for l=1,#list do
- local ll = list[l]
+ local ll = list[l]
local ltg = ll.tg
if ltg then
local lns = ll.rn or ll.ns
- local ok = false
+ local ok = false
for n=1,maxn,3 do
- local nns, ntg = nodes[n+1], nodes[n+2]
+ local nns = nodes[n+1]
+ local ntg = nodes[n+2]
ok = (not ntg or ltg == ntg) and (not nns or lns == nns)
if ok then
break
@@ -485,14 +556,16 @@ local function apply_nodes(list,directive,nodes)
end
if directive then
if ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
elseif not ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
+ local llp = ll.__p__ ; if llp ~= p then p = llp ; m = 1 else m = m + 1 end
c = c + 1
- collected[c], ll.mi = ll, m
+ collected[c] = ll
+ ll.mi = m
end
end
end
@@ -503,7 +576,8 @@ end
local quit_expression = false
local function apply_expression(list,expression,order)
- local collected, c = { }, 0
+ local collected = { }
+ local c = 0
quit_expression = false
for l=1,#list do
local ll = list[l]
@@ -900,7 +974,8 @@ local function tagstostring(list)
local t = { }
for i=1, #list do
local li = list[i]
- local ns, tg = li.ns, li.tg
+ local ns = li.ns
+ local tg = li.tg
if not ns or ns == "" then ns = "*" end
if not tg or tg == "" then tg = "*" end
t[i] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
@@ -1365,7 +1440,8 @@ expressions.name = function(e,n) -- ns + tg
if n == 0 then
found = type(e) == "table" and e
elseif n < 0 then
- local d, k = e.__p__.dt, e.ni
+ local d = e.__p__.dt
+ local k = e.ni
for i=k-1,1,-1 do
local di = d[i]
if type(di) == "table" then
@@ -1378,7 +1454,8 @@ expressions.name = function(e,n) -- ns + tg
end
end
else
- local d, k = e.__p__.dt, e.ni
+ local d = e.__p__.dt
+ local k = e.ni
for i=k+1,#d,1 do
local di = d[i]
if type(di) == "table" then
@@ -1392,7 +1469,8 @@ expressions.name = function(e,n) -- ns + tg
end
end
if found then
- local ns, tg = found.rn or found.ns or "", found.tg
+ local ns = found.rn or found.ns or ""
+ local tg = found.tg
if ns ~= "" then
return ns .. ":" .. tg
else
@@ -1412,7 +1490,8 @@ expressions.tag = function(e,n) -- only tg
if n == 0 then
found = (type(e) == "table") and e -- seems to fail
elseif n < 0 then
- local d, k = e.__p__.dt, e.ni
+ local d = e.__p__.dt
+ local k = e.ni
for i=k-1,1,-1 do
local di = d[i]
if type(di) == "table" then
@@ -1425,7 +1504,8 @@ expressions.tag = function(e,n) -- only tg
end
end
else
- local d, k = e.__p__.dt, e.ni
+ local d = e.__p__.dt
+ local k = e.ni
for i=k+1,#d,1 do
local di = d[i]
if type(di) == "table" then
@@ -1592,8 +1672,8 @@ end
-- local w = lpeg.patterns.whitespace
-- local p = w^0 * lpeg.Cf(lpeg.Ct("") * lpeg.Cg(lpeg.C((1-w)^1) * lpeg.Cc(true) * w^0)^1,rawset)
--- function xml.functions.classes(e) -- cache
--- local class = e.at.class
+-- function xml.functions.classes(e,class) -- cache
+-- class = class and e.at[class] or e.at.class
-- if class then
-- return lpegmatch(p,class)
-- else
diff --git a/tex/context/base/mkiv/lxml-tex.lua b/tex/context/base/mkiv/lxml-tex.lua
index b8280ba9c..ae3edba56 100644
--- a/tex/context/base/mkiv/lxml-tex.lua
+++ b/tex/context/base/mkiv/lxml-tex.lua
@@ -92,6 +92,8 @@ local forceraw = false
local p_texescape = patterns.texescape
+local tokenizedcs = context.tokenizedcs
+
directives.enable("xml.path.keeplastmatch")
-- tex entities
@@ -499,13 +501,29 @@ function lxml.checkindex(name)
return root and root.index or 0
end
-function lxml.withindex(name,n,command) -- will change as name is always there now
- local i, p = lpegmatch(splitter,n)
- if p then
- contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",n,"}")
- else
- contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",name,"::",n,"}")
+if tokenizedcs then
+
+ function lxml.withindex(name,n,command) -- will change as name is always there now
+ local i, p = lpegmatch(splitter,n)
+ local w = tokenizedcs.xmlw
+ if p then
+ contextsprint(ctxcatcodes,w,"{",command,"}{",n,"}")
+ else
+ contextsprint(ctxcatcodes,w,"{",command,"}{",name,"::",n,"}")
+ end
+ end
+
+else
+
+ function lxml.withindex(name,n,command) -- will change as name is always there now
+ local i, p = lpegmatch(splitter,n)
+ if p then
+ contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",n,"}")
+ else
+ contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",name,"::",n,"}")
+ end
end
+
end
function lxml.getindex(name,n) -- will change as name is always there now
@@ -728,21 +746,6 @@ end
local default_element_handler = xml.gethandlers("verbose").functions["@el@"]
--- local xmlw = setmetatableindex(function(t,k)
--- local v = setmetatableindex(function(t,kk)
--- local v
--- if kk == false then
--- v = "\\xmlw{" .. k .. "}{"
--- else
--- v = "\\xmlw{" .. k .. "}{" .. kk .. "::"
--- end
--- t[kk] = v
--- return v
--- end)
--- t[k]= v
--- return v
--- end)
-
local setfilename = false
local trace_name = false
local report_name = logs.reporter("lxml")
@@ -765,39 +768,80 @@ trackers.register("system.synctex.xml",function(v)
trace_name = v
end)
-local function tex_element(e,handlers)
- if setfilename then
- syncfilename(e,"element")
- end
- local command = e.command
- if command == nil then
- default_element_handler(e,handlers)
- elseif command == true then
- -- text (no <self></self>) / so, no mkii fallback then
- handlers.serialize(e.dt,handlers)
- elseif command == false then
- -- ignore
- else
- local tc = type(command)
- if tc == "string" then
- local rootname, ix = e.name, e.ix
- if rootname then
- if not ix then
- addindex(rootname,false,true)
- ix = e.ix
+local tex_element
+
+if tokenizedcs then
+
+ tex_element = function(e,handlers)
+ if setfilename then
+ syncfilename(e,"element")
+ end
+ local command = e.command
+ if command == nil then
+ default_element_handler(e,handlers)
+ elseif command == true then
+ -- text (no <self></self>) / so, no mkii fallback then
+ handlers.serialize(e.dt,handlers)
+ elseif command == false then
+ -- ignore
+ else
+ local tc = type(command)
+ if tc == "string" then
+ local rootname, ix = e.name, e.ix
+ local w = tokenizedcs.xmlw
+ if rootname then
+ if not ix then
+ addindex(rootname,false,true)
+ ix = e.ix
+ end
+ contextsprint(ctxcatcodes,w,"{",command,"}{",rootname,"::",ix,"}")
+ else
+ report_lxml("fatal error: no index for %a",command)
+ contextsprint(ctxcatcodes,w,"{",command,"}{",ix or 0,"}")
end
- -- faster than context.xmlw
- contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",rootname,"::",ix,"}")
- -- contextsprint(ctxcatcodes,xmlw[command][rootname],ix,"}")
- else
- report_lxml("fatal error: no index for %a",command)
- contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",ix or 0,"}")
- -- contextsprint(ctxcatcodes,xmlw[command][false],ix or 0,"}")
+ elseif tc == "function" then
+ command(e)
+ end
+ end
+ end
+
+else
+
+ tex_element = function(e,handlers)
+ if setfilename then
+ syncfilename(e,"element")
+ end
+ local command = e.command
+ if command == nil then
+ default_element_handler(e,handlers)
+ elseif command == true then
+ -- text (no <self></self>) / so, no mkii fallback then
+ handlers.serialize(e.dt,handlers)
+ elseif command == false then
+ -- ignore
+ else
+ local tc = type(command)
+ if tc == "string" then
+ local rootname, ix = e.name, e.ix
+ if rootname then
+ if not ix then
+ addindex(rootname,false,true)
+ ix = e.ix
+ end
+ -- faster than context.xmlw
+ contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",rootname,"::",ix,"}")
+ -- contextsprint(ctxcatcodes,xmlw[command][rootname],ix,"}")
+ else
+ report_lxml("fatal error: no index for %a",command)
+ contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",ix or 0,"}")
+ -- contextsprint(ctxcatcodes,xmlw[command][false],ix or 0,"}")
+ end
+ elseif tc == "function" then
+ command(e)
end
- elseif tc == "function" then
- command(e)
end
end
+
end
-- <?context-directive foo ... ?>
@@ -1180,7 +1224,7 @@ function lxml.flushsetups(id,...)
local sd = setups[document]
if sd then
for k=1,#sd do
- local v= sd[k]
+ local v = sd[k]
if not done[v] then
if trace_loading then
report_lxml("applying setup %02i : %a to %a",k,v,document)
@@ -1442,29 +1486,63 @@ end
-- the number of commands is often relative small but there can be many calls
-- to this finalizer
-local function command(collected,cmd,otherwise)
- local n = collected and #collected
- if n and n > 0 then
- local wildcard = find(cmd,"*",1,true)
- for c=1,n do -- maybe optimize for n=1
- local e = collected[c]
- local ix = e.ix
- local name = e.name
- if name and not ix then
- addindex(name,false,true)
- ix = e.ix
- end
- if not ix or not name then
- report_lxml("no valid node index for element %a using command %s",name or "?",cmd)
- elseif wildcard then
- contextsprint(ctxcatcodes,"\\xmlw{",(gsub(cmd,"%*",e.tg)),"}{",name,"::",ix,"}")
- else
- contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",name,"::",ix,"}")
+local command
+
+if tokenizedcs then
+
+ command = function(collected,cmd,otherwise)
+ local n = collected and #collected
+ local w = tokenizedcs.xmlw
+ if n and n > 0 then
+ local wildcard = find(cmd,"*",1,true)
+ for c=1,n do -- maybe optimize for n=1
+ local e = collected[c]
+ local ix = e.ix
+ local name = e.name
+ if name and not ix then
+ addindex(name,false,true)
+ ix = e.ix
+ end
+ if not ix or not name then
+ report_lxml("no valid node index for element %a using command %s",name or "?",cmd)
+ elseif wildcard then
+ contextsprint(ctxcatcodes,w,"{",(gsub(cmd,"%*",e.tg)),"}{",name,"::",ix,"}")
+ else
+ contextsprint(ctxcatcodes,w,"{",cmd,"}{",name,"::",ix,"}")
+ end
+ end
+ elseif otherwise then
+ contextsprint(ctxcatcodes,w,"{",otherwise,"}{#1}")
+ end
+ end
+
+else
+
+ command = function(collected,cmd,otherwise)
+ local n = collected and #collected
+ if n and n > 0 then
+ local wildcard = find(cmd,"*",1,true)
+ for c=1,n do -- maybe optimize for n=1
+ local e = collected[c]
+ local ix = e.ix
+ local name = e.name
+ if name and not ix then
+ addindex(name,false,true)
+ ix = e.ix
+ end
+ if not ix or not name then
+ report_lxml("no valid node index for element %a using command %s",name or "?",cmd)
+ elseif wildcard then
+ contextsprint(ctxcatcodes,"\\xmlw{",(gsub(cmd,"%*",e.tg)),"}{",name,"::",ix,"}")
+ else
+ contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",name,"::",ix,"}")
+ end
end
+ elseif otherwise then
+ contextsprint(ctxcatcodes,"\\xmlw{",otherwise,"}{#1}")
end
- elseif otherwise then
- contextsprint(ctxcatcodes,"\\xmlw{",otherwise,"}{#1}")
end
+
end
-- local wildcards = setmetatableindex(function(t,k)
@@ -1675,7 +1753,7 @@ local function concatrange(collected,start,stop,separator,lastseparator,textonly
end
end
-local function concat(collected,separator,lastseparator,textonly) -- test this on mml
+local function concatlist(collected,separator,lastseparator,textonly) -- test this on mml
concatrange(collected,false,false,separator,lastseparator,textonly)
end
@@ -1697,14 +1775,12 @@ texfinalizers.context = ctxtext
texfinalizers.position = position
texfinalizers.match = match
texfinalizers.index = index
-texfinalizers.concat = concat
+texfinalizers.concat = concatlist
texfinalizers.concatrange = concatrange
texfinalizers.chainattribute = chainattribute
texfinalizers.chainpath = chainpath
texfinalizers.default = all -- !!
-local concat = table.concat
-
function texfinalizers.tag(collected,n)
if collected then
local nc = #collected
@@ -1997,7 +2073,7 @@ do
implement {
name = "xmldoifatt",
arguments = "3 strings",
- actions = function(id,l,v)
+ actions = function(id,k,v)
local e = getid(id)
ctx_doif(e and e.at[k] == v or false)
end
@@ -2006,7 +2082,7 @@ do
implement {
name = "xmldoifnotatt",
arguments = "3 strings",
- actions = function(id,l,v)
+ actions = function(id,k,v)
local e = getid(id)
ctx_doifnot(e and e.at[k] == v or false)
end
@@ -2015,7 +2091,7 @@ do
implement {
name = "xmldoifelseatt",
arguments = "3 strings",
- actions = function(id,l,v)
+ actions = function(id,k,v)
local e = getid(id)
ctx_doifelse(e and e.at[k] == v or false)
end
@@ -2139,24 +2215,51 @@ function lxml.direct(id)
end
end
-function lxml.command(id,pattern,cmd)
- local i, p = getid(id,true)
- local collected = xmlapplylpath(getid(i),pattern)
- if collected then
- local nc = #collected
- if nc > 0 then
- local rootname = p or i.name
- for c=1,nc do
- local e = collected[c]
- local ix = e.ix
- if not ix then
- addindex(rootname,false,true)
- ix = e.ix
+if tokenizedcs then
+
+ function lxml.command(id,pattern,cmd)
+ local i, p = getid(id,true)
+ local collected = xmlapplylpath(getid(i),pattern)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ local rootname = p or i.name
+ local w = tokenizedcs.xmlw
+ for c=1,nc do
+ local e = collected[c]
+ local ix = e.ix
+ if not ix then
+ addindex(rootname,false,true)
+ ix = e.ix
+ end
+ contextsprint(ctxcatcodes,w,"{",cmd,"}{",rootname,"::",ix,"}")
+ end
+ end
+ end
+ end
+
+else
+
+ function lxml.command(id,pattern,cmd)
+ local i, p = getid(id,true)
+ local collected = xmlapplylpath(getid(i),pattern)
+ if collected then
+ local nc = #collected
+ if nc > 0 then
+ local rootname = p or i.name
+ for c=1,nc do
+ local e = collected[c]
+ local ix = e.ix
+ if not ix then
+ addindex(rootname,false,true)
+ ix = e.ix
+ end
+ contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",rootname,"::",ix,"}")
end
- contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",rootname,"::",ix,"}")
end
end
end
+
end
-- loops
@@ -2292,13 +2395,13 @@ function texfinalizers.lettered(collected)
end
end
---~ function texfinalizers.apply(collected,what) -- to be tested
---~ if collected then
---~ for c=1,#collected do
---~ contextsprint(ctxcatcodes,what(collected[c].dt[1]))
---~ end
---~ end
---~ end
+-- function texfinalizers.apply(collected,what) -- to be tested
+-- if collected then
+-- for c=1,#collected do
+-- contextsprint(ctxcatcodes,what(collected[c].dt[1]))
+-- end
+-- end
+-- end
function lxml.toparameters(id)
local e = getid(id)
@@ -2357,49 +2460,56 @@ end
-- parameters
-function lxml.setatt(id,name,value)
- local e = getid(id)
- if e then
- local a = e.at
- if a then
- a[name] = value
- else
- e.at = { [name] = value }
+do
+
+ local function setatt(id,name,value)
+ local e = getid(id)
+ if e then
+ local a = e.at
+ if a then
+ a[name] = value
+ else
+ e.at = { [name] = value }
+ end
end
end
-end
-function lxml.setpar(id,name,value)
- local e = getid(id)
- if e then
- local p = e.pa
- if p then
- p[name] = value
- else
- e.pa = { [name] = value }
+ local function setpar(id,name,value)
+ local e = getid(id)
+ if e then
+ local p = e.pa
+ if p then
+ p[name] = value
+ else
+ e.pa = { [name] = value }
+ end
end
end
-end
-function lxml.setattribute(id,pattern,name,value)
- local collected = xmlapplylpath(getid(id),pattern)
- if collected then
- for i=1,#collected do
- setatt(collected[i],name,value)
+ lxml.setatt = setatt
+ lxml.setpar = setpar
+
+ function lxml.setattribute(id,pattern,name,value)
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected then
+ for i=1,#collected do
+ setatt(collected[i],name,value)
+ end
end
end
-end
-function lxml.setparameter(id,pattern,name,value)
- local collected = xmlapplylpath(getid(id),pattern)
- if collected then
- for i=1,#collected do
- setpar(collected[i],name,value)
+ function lxml.setparameter(id,pattern,name,value)
+ local collected = xmlapplylpath(getid(id),pattern)
+ if collected then
+ for i=1,#collected do
+ setpar(collected[i],name,value)
+ end
end
end
-end
-lxml.setparam = lxml.setparameter
+ lxml.setparam = lxml.setparameter
+
+end
-- relatively new:
@@ -2629,3 +2739,59 @@ function texfinalizers.xml(collected,name,setup)
buffers.assign(name,strip(xmltostring(root)))
context.xmlprocessbuffer(name,name,setup or (name..":setup"))
end
+
+-- experiment
+
+do
+
+ local xmltoelement = xml.toelement
+ local xmlreindex = xml.reindex
+
+ function lxml.replace(root,pattern,whatever)
+ if type(root) == "string" then
+ root = lxml.getid(root)
+ end
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ local isstring = type(whatever) == "string"
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ local d = p.dt
+ local n = e.ni
+ local w = isstring and whatever or whatever(e)
+ if w then
+ local t = xmltoelement(w,root).dt
+ if t then
+ t.__p__ = p
+ if type(t) == "table" then
+ local t1 = t[1]
+ d[n] = t1
+ t1.at.type = e.at.type or t1.at.type
+ for i=2,#t do
+ n = n + 1
+ insert(d,n,t[i])
+ end
+ else
+ d[n] = t
+ end
+ xmlreindex(d) -- probably not needed
+ end
+ end
+ end
+ end
+ end
+ end
+
+ -- function document.mess_around(root)
+ -- lxml.replace(
+ -- root,
+ -- "p[@variant='foo']",
+ -- function(c)
+ -- return (string.gsub(tostring(c),"foo","<bar>%1</bar>"))
+ -- end
+ -- )
+ -- end
+
+end
diff --git a/tex/context/base/mkiv/m-fonts-plugins.mkiv b/tex/context/base/mkiv/m-fonts-plugins.mkiv
index b74b8c3d0..154e47804 100644
--- a/tex/context/base/mkiv/m-fonts-plugins.mkiv
+++ b/tex/context/base/mkiv/m-fonts-plugins.mkiv
@@ -186,6 +186,7 @@
\definefontfeature
[arabic-node]
[arabic]
+ [salt=yes] % seems to be needed for husayni
\definefontfeature
[arabic-native]
@@ -224,7 +225,7 @@
\getbuffer[#5-definitions]
\showfontkerns
\showmakeup[discretionary]
- \enabletrackers[fonts.plugins.hb.colors]%
+ % \enabletrackers[fonts.plugins.hb.colors]%
\testfeatureonce{1}{
\getbuffer[#5-text]
}
@@ -263,7 +264,7 @@
\title{#1 #3 #4}
\start
\getbuffer[#5-definitions]
- \enabletrackers[fonts.plugins.hb.colors]%
+ % \enabletrackers[fonts.plugins.hb.colors]%
\testfeatureonce{1}{
\setupalign[flushleft] % easier to compare
\getbuffer[#5-text]
diff --git a/tex/context/base/mkiv/math-act.lua b/tex/context/base/mkiv/math-act.lua
index 77a355b22..07ef32746 100644
--- a/tex/context/base/mkiv/math-act.lua
+++ b/tex/context/base/mkiv/math-act.lua
@@ -23,6 +23,12 @@ local mathematics = mathematics
local texsetdimen = tex.setdimen
local abs = math.abs
+local helpers = fonts.helpers
+local upcommand = helpers.commands.up
+local rightcommand = helpers.commands.right
+local charcommand = helpers.commands.char
+local prependcommands = helpers.prependcommands
+
local sequencers = utilities.sequencers
local appendgroup = sequencers.appendgroup
local appendaction = sequencers.appendaction
@@ -237,7 +243,6 @@ function mathematics.overloaddimensions(target,original,set)
local factor = parameters.factor
local hfactor = parameters.hfactor
local vfactor = parameters.vfactor
- local addprivate = fonts.helpers.addprivate
-- to be sure
target.type = "virtual"
target.properties.virtualized = true
@@ -257,7 +262,8 @@ function mathematics.overloaddimensions(target,original,set)
local height = data.height
local depth = data.depth
if trace_defining and (width or height or depth) then
- report_math("overloading dimensions of %C, width %a, height %a, depth %a",unicode,width,height,depth)
+ report_math("overloading dimensions of %C, width %p, height %p, depth %p",
+ unicode,width or 0,height or 0,depth or 0)
end
if width then character.width = width * hfactor end
if height then character.height = height * vfactor end
@@ -270,25 +276,26 @@ function mathematics.overloaddimensions(target,original,set)
if d then
xoffset = - d.boundingbox[1] * hfactor
character.width = character.width + xoffset
- xoffset = { "right", xoffset }
+ xoffset = rightcommand[xoffset]
+ else
+ xoffset = nil
end
- elseif xoffset then
- xoffset = { "right", xoffset * hfactor }
+ elseif xoffset and xoffset ~= 0 then
+ xoffset = rightcommand[xoffset * hfactor]
+ else
+ xoffset = nil
end
- if yoffset then
- yoffset = { "down", -yoffset * vfactor }
+ if yoffset and yoffset ~= 0 then
+ yoffset = upcommand[yoffset * vfactor]
+ else
+ yoffset = nil
end
if xoffset or yoffset then
- if character.commands then
- if yoffset then
- insert(character.commands,1,yoffset)
- end
- if xoffset then
- insert(character.commands,1,xoffset)
- end
+ local commands = characters.commands
+ if commands then
+ prependcommands(commands,yoffset,xoffset)
else
- -- local slot = { "slot", 1, addprivate(target,nil,fastcopy(character)) }
- local slot = { "slot", 0, addprivate(target,nil,fastcopy(character)) }
+ local slot = charcommand[unicode]
if xoffset and yoffset then
character.commands = { xoffset, yoffset, slot }
elseif xoffset then
@@ -297,7 +304,6 @@ function mathematics.overloaddimensions(target,original,set)
character.commands = { yoffset, slot }
end
end
- character.index = nil
end
elseif trace_defining then
report_math("no overloading dimensions of %C, not in font",unicode)
@@ -732,9 +738,9 @@ function mathematics.finishfallbacks(target,specification,fallbacks)
done[unic] = true
end
end
+ local step = offset - start
for unicode = start, stop do
- local unic = unicode + offset - start
- remap(unic,unicode,false)
+ remap(unicode + step,unicode,false)
end
if gaps then
for unic, unicode in next, gaps do
diff --git a/tex/context/base/mkiv/math-ali.mkiv b/tex/context/base/mkiv/math-ali.mkiv
index 083fb7645..ecfac6887 100644
--- a/tex/context/base/mkiv/math-ali.mkiv
+++ b/tex/context/base/mkiv/math-ali.mkiv
@@ -321,11 +321,18 @@
\def\math_alignment_EQ
{\NC=}
+\installmacrostack\NC % maybe more to shared table definitions
+\installmacrostack\NN % maybe more to shared table definitions
+\installmacrostack\EQ % maybe more to shared table definitions
+\installmacrostack\NR % maybe more to shared table definitions
+\installmacrostack\BC % maybe more to shared table definitions
+\installmacrostack\EC % maybe more to shared table definitions
+
\appendtoks
- \pushmacro\NC
- \pushmacro\NN
- \pushmacro\EQ
- \pushmacro\NR
+ \push_macro_NC
+ \push_macro_NN
+ \push_macro_EQ
+ \push_macro_NR
\let\NC\math_alignment_NC
\let\NN\math_alignment_NN
\let\EQ\math_alignment_EQ
@@ -334,10 +341,10 @@
\to \everymathalignment
\appendtoks
- \popmacro\NR
- \popmacro\EQ
- \popmacro\NN
- \popmacro\NC
+ \pop_macro_NR
+ \pop_macro_EQ
+ \pop_macro_NN
+ \pop_macro_NC
\to \everymathalignmentdone
\let\math_alignment_snap_start\relax
@@ -694,11 +701,11 @@
{\unskip
\math_cases_end_math
\aligntab
- \global\let\math_cases_NC\math_cases_NC_first
+ \glet\math_cases_NC\math_cases_NC_first
\dodirectdoubleempty\math_cases_NR}
\def\math_cases_NC_first
- {\global\let\math_cases_NC\math_cases_NC_second}
+ {\glet\math_cases_NC\math_cases_NC_second}
\def\math_cases_NC_second
{\math_cases_end_math\aligntab}
@@ -722,7 +729,7 @@
\let\NC\math_cases_NC_zero
\let\MC\math_cases_MC_zero
\let\NR\math_cases_NR_zero
- \global\let\math_cases_NC\math_cases_NC_first
+ \glet\math_cases_NC\math_cases_NC_first
\normalbaselines
\mathsurround\zeropoint
\everycr\emptytoks
diff --git a/tex/context/base/mkiv/math-arr.mkiv b/tex/context/base/mkiv/math-arr.mkiv
index a0dda66b9..2edb91465 100644
--- a/tex/context/base/mkiv/math-arr.mkiv
+++ b/tex/context/base/mkiv/math-arr.mkiv
@@ -67,39 +67,46 @@
\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\m_math_arrows_factor{1}%
- \def\m_math_arrows_extra {0}%
+ \let\m_math_arrows_factor\!!plusone
+ \let\m_math_arrows_extra \!!zerocount
\edef\p_math_spacing{#1}%
\csname\??matharrowsettings
\ifcsname\??matharrowsettings\p_math_spacing\endcsname\p_math_spacing\else\s!unknown\fi
\endcsname
\mathsurround\zeropoint
- \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{\normalstartimath
- \scriptstyle
- \mkern\muskip0\relax
- #5\relax
- \mkern\muskip2\relax
- \normalstopimath}%
- \setbox2\hbox{\normalstartimath
- \scriptstyle
- \mkern\muskip0\relax
- #4\relax
- \mkern\muskip2\relax
- \normalstopimath}%
- \setbox4\hbox{#3\displaystyle}%
- \dimen0\wd0\relax
- \ifdim\wd2>\dimen0
- \dimen0\wd2\relax
+ \scratchmuskipone\muexpr\m_math_arrows_factor\muexpr\thirdoffourarguments #2\onemuskip\relax+\m_math_arrows_extra\onemuskip+\firstoffourarguments #2\onemuskip\relax
+ \scratchmuskiptwo\muexpr\m_math_arrows_factor\muexpr\fourthoffourarguments#2\onemuskip\relax+\m_math_arrows_extra\onemuskip+\secondoffourarguments#2\onemuskip\relax
+ \setbox\scratchboxone\hbox
+ {\normalstartimath
+ \scriptstyle
+ \mkern\scratchmuskipone\relax
+ #5\relax
+ \mkern\scratchmuskiptwo\relax
+ \normalstopimath}%
+ \setbox\scratchboxtwo\hbox
+ {\normalstartimath
+ \scriptstyle
+ \mkern\scratchmuskipone\relax
+ #4\relax
+ \mkern\scratchmuskiptwo\relax
+ \normalstopimath}%
+ \setbox\scratchboxthree\hbox{#3\displaystyle}%
+ \scratchdimenone\wd\scratchboxone\relax
+ \ifdim\wd\scratchboxtwo>\scratchdimenone
+ \scratchdimenone\wd\scratchboxtwo\relax
\fi
- \ifdim\wd4>\dimen0
- \dimen0\wd4\relax
+ \ifdim\wd\scratchboxthree>\scratchdimenone
+ \scratchdimenone\wd\scratchboxthree\relax
\fi
- \ifdim\wd4=\dimen0\else
- \setbox4\hbox to \dimen0{#3\displaystyle}%
+ \ifdim\wd\scratchboxthree=\scratchdimenone\else
+ \setbox\scratchboxthree\hbox to \scratchdimenone{#3\displaystyle}%
\fi
- \mathrel{\mathop{\hbox to \dimen0{\hss\copy4\hss}}\limits\normalsuperscript{\box0}\normalsubscript{\box2}}% pack ?
+ \mathrel
+ {\mathop
+ {\hpack to \scratchdimenone{\hss\box\scratchboxthree\hss}}% pack ? copy ?
+ \limits
+ \normalsuperscript{\box\scratchboxone}%
+ \normalsubscript {\box\scratchboxtwo}}%
\endgroup}
\let\math_arrows_construct_single\math_arrows_construct
diff --git a/tex/context/base/mkiv/math-dim.lua b/tex/context/base/mkiv/math-dim.lua
index 72b9d7e50..eb7adb53f 100644
--- a/tex/context/base/mkiv/math-dim.lua
+++ b/tex/context/base/mkiv/math-dim.lua
@@ -157,7 +157,8 @@ function mathematics.dimensions(dimens) -- beware, dimens get spoiled
for variable, styles in next, defaults do
local tt = { }
for style, default in next, styles do
- local one, two = default[1], default[2]
+ local one = default[1]
+ local two = default[2]
local value = dimens[one]
if value then
tt[style] = value
diff --git a/tex/context/base/mkiv/math-dir.lua b/tex/context/base/mkiv/math-dir.lua
index 759f1e797..38aa44358 100644
--- a/tex/context/base/mkiv/math-dir.lua
+++ b/tex/context/base/mkiv/math-dir.lua
@@ -48,7 +48,9 @@ local vlist_code = nodecodes.vlist
local nodepool = nuts.pool
-local new_textdir = nodepool.textdir
+local new_direction = nodepool.direction
+
+local lefttoright_code = nodes.dirvalues.lefttoright
local chardirections = characters.directions
local charmirrors = characters.mirrors
@@ -60,16 +62,14 @@ local a_mathbidi = attributes.private('mathbidi')
local function processmath(head)
local current = head
- local done = false
local start = nil
local stop = nil
local function capsulate()
- head = insert_node_before(head,start,new_textdir("+TLT"))
- insert_node_after(head,stop,new_textdir("-TLT"))
+ head = insert_node_before(head,start,new_direction(lefttoright_code))
+ insert_node_after(head,stop,new_direction(lefttoright_code,true))
if trace_directions then
report_directions("reversed: %s",nodes.listtoutf(start,false,false,stop))
end
- done = true
start = false
stop = nil
end
@@ -100,7 +100,6 @@ local function processmath(head)
if trace_directions then
report_directions("mirrored: %C to %C",char,mirror)
end
- done = true
end
end
end
@@ -108,11 +107,8 @@ local function processmath(head)
elseif not start then
-- nothing
if id == hlist_code or id == vlist_code then
- local list, d = processmath(getlist(current))
+ local list = processmath(getlist(current))
setlist(current,list)
- if d then
- done = true
- end
end
elseif start == stop then
start = nil
@@ -121,11 +117,8 @@ local function processmath(head)
-- math can pack things into hlists .. we need to make sure we don't process
-- too often: needs checking
if id == hlist_code or id == vlist_code then
- local list, d = processmath(getlist(current))
+ local list = processmath(getlist(current))
setlist(current,list)
- if d then
- done = true
- end
end
end
current = getnext(current)
@@ -137,21 +130,18 @@ local function processmath(head)
else
capsulate()
end
- return head, done
+ return head
end
local enabled = false
function directions.processmath(head) -- style, penalties
if enabled then
- local h = tonut(head)
- local a = getattr(h,a_mathbidi)
+ local a = getattr(head,a_mathbidi)
if a and a > 0 then
- local head, done = processmath(h)
- return tonode(head), done
+ return processmath(head)
end
end
- return head, false
end
function directions.setmath(n)
diff --git a/tex/context/base/mkiv/math-ext.lua b/tex/context/base/mkiv/math-ext.lua
index a4b865713..b923853f4 100644
--- a/tex/context/base/mkiv/math-ext.lua
+++ b/tex/context/base/mkiv/math-ext.lua
@@ -7,29 +7,30 @@ if not modules then modules = { } end modules ['math-ext'] = {
}
local rawget = rawget
-
-local trace_virtual = false trackers.register("math.virtual", function(v) trace_virtual = v end)
-
local basename = file.basename
+local sortedhash = table.sortedhash
+
+local mathematics = mathematics
+local extras = mathematics.extras or { }
+mathematics.extras = extras
-local mathematics = mathematics
-local characters = characters
+local characters = characters
+local chardata = characters.data
+local mathpairs = characters.mathpairs
-local report_math = logs.reporter("mathematics")
+local trace_virtual = false
+local report_math = logs.reporter("mathematics")
-mathematics.extras = mathematics.extras or { }
-local extras = mathematics.extras
+trackers.register("math.virtual", function(v) trace_virtual = v end)
-local mathplus = { }
-local chardata = characters.data
-local mathpairs = characters.mathpairs
+local mathplus = { }
-- todo: store them and skip storage if already stored
-- todo: make a char-ctx.lua (or is this already side effect of save in format)
local function addextra(unicode)
local min = mathematics.extrabase
- local max = mathematics.privatebase - 1
+ local max = min + 0xFFF
if unicode >= min and unicode <= max then
if chardata[unicode] then
mathplus[unicode] = true
@@ -47,7 +48,7 @@ function extras.copy(target,original)
local characters = target.characters
local properties = target.properties
local parameters = target.parameters
- for unicode in table.sortedhash(mathplus) do
+ for unicode in sortedhash(mathplus) do
local extradesc = chardata[unicode]
local nextinsize = extradesc.nextinsize
if nextinsize then
diff --git a/tex/context/base/mkiv/math-fbk.lua b/tex/context/base/mkiv/math-fbk.lua
index 7aa8c437f..963461de5 100644
--- a/tex/context/base/mkiv/math-fbk.lua
+++ b/tex/context/base/mkiv/math-fbk.lua
@@ -20,10 +20,22 @@ local sortedhash = table.sortedhash
local fallbacks = { }
mathematics.fallbacks = fallbacks
+local helpers = fonts.helpers
+local prependcommands = helpers.prependcommands
+local charcommand = helpers.commands.char
+local leftcommand = helpers.commands.left
+local rightcommand = helpers.commands.right
+local upcommand = helpers.commands.up
+local downcommand = helpers.commands.down
+local dummycommand = helpers.commands.dummy
+local popcommand = helpers.commands.pop
+local pushcommand = helpers.commands.push
+
local virtualcharacters = { }
-local identifiers = fonts.hashes.identifiers
-local lastmathids = fonts.hashes.lastmathids
+local hashes = fonts.hashes
+local identifiers = hashes.identifiers
+local lastmathids = 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
@@ -115,6 +127,8 @@ function fallbacks.apply(target,original)
}
target.mathrelation = data
--
+ local fullname = trace_fallbacks and target.properties.fullname
+ --
for k, v in sortedhash(virtualcharacters) do
if not characters[k] then
local tv = type(v)
@@ -132,7 +146,7 @@ function fallbacks.apply(target,original)
-- something else
end
if trace_fallbacks and characters[k] then
- report_fallbacks("extending math font %a with %U",target.properties.fullname,k)
+ report_fallbacks("extending math font %a with %U",fullname,k)
end
end
end
@@ -151,22 +165,21 @@ local function reference(index,char)
if index then
return { "slot", index, char }
else
- return { "char", char }
+ return charcommand[char]
end
end
-local function raised(data,down)
- local replacement = data.replacement
- local character = data.scriptdata.characters[replacement]
+local function raised(data,replacement,down)
+ local character = data.scriptdata.characters[replacement]
if character then
+ local size = data.size
return {
width = character.width,
height = character.height,
depth = character.depth,
commands = {
- { "down", down and data.size/4 or -data.size/2 }, -- maybe exheight
+ down and downcommand[size/4] or upcommand[size/2],
reference(data.scriptindex,replacement)
- -- { "slot", data.scriptindex or 0, char } -- hm, data.mathrelation.scriptindex
}
}
end
@@ -177,33 +190,18 @@ end
-- virtualcharacters[0x208A] = 0x2212
-- virtualcharacters[0x208B] = 0x002B
-virtualcharacters[0x207A] = function(data)
- data.replacement = 0x002B
- return raised(data)
-end
-
-virtualcharacters[0x207B] = function(data)
- data.replacement = 0x2212
- return raised(data)
-end
-
-virtualcharacters[0x208A] = function(data)
- data.replacement = 0x002B
- return raised(data,true)
-end
-
-virtualcharacters[0x208B] = function(data)
- data.replacement = 0x2212
- return raised(data,true)
-end
+virtualcharacters[0x207A] = function(data) return raised(data,0x002B) end
+virtualcharacters[0x207B] = function(data) return raised(data,0x2212) end
+virtualcharacters[0x208A] = function(data) return raised(data,0x002B,true) end
+virtualcharacters[0x208B] = function(data) return raised(data,0x2212,true) end
-- local function repeated(data,char,n,fraction)
-- local character = data.characters[char]
-- if character then
-- local width = character.width
-- local delta = width - character.italic -- width * fraction
--- local c = { "char", char }
--- local r = { "right", right }
+-- local c = charcommand[char]
+-- local r = rightcommand[right]
-- local commands = { }
-- for i=1,n-1 do
-- width = width + delta
@@ -234,14 +232,9 @@ addextra(0xFE350) -- MATHEMATICAL DOUBLE ARROW LEFT END
addextra(0xFE351) -- MATHEMATICAL DOUBLE ARROW MIDDLE PART
addextra(0xFE352) -- MATHEMATICAL DOUBLE ARROW RIGHT END
-local push = { "push" }
-local pop = { "pop" }
-local leftarrow = { "char", 0x2190 }
-local relbar = { "char", 0x2212 }
-local rightarrow = { "char", 0x2192 }
--- local leftarrow = { "slot", 0, 0x2190 }
--- local relbar = { "slot", 0, 0x2212 }
--- local rightarrow = { "slot", 0, 0x2192 }
+local leftarrow = charcommand[0x2190]
+local relbar = charcommand[0x2212]
+local rightarrow = charcommand[0x2192]
virtualcharacters[0xFE350] = function(data)
-- return combined(data,0x2190,0x2212) -- leftarrow relbar
@@ -254,11 +247,11 @@ virtualcharacters[0xFE350] = function(data)
height = size,
depth = size,
commands = {
- push,
- { "down", size/2 },
+ pushcommand,
+ downcommand[size/2],
leftarrow,
- pop,
- { "down", -size/2 },
+ popcommand,
+ upcommand[size/2],
relbar,
}
}
@@ -275,11 +268,11 @@ virtualcharacters[0xFE351] = function(data)
height = size,
depth = size,
commands = {
- push,
- { "down", size/2 },
+ pushcommand,
+ downcommand[size/2],
relbar,
- pop,
- { "down", -size/2 },
+ popcommand,
+ upcommand[size/2],
relbar,
}
}
@@ -297,12 +290,12 @@ virtualcharacters[0xFE352] = function(data)
height = size,
depth = size,
commands = {
- push,
- { "down", size/2 },
+ pushcommand,
+ downcommand[size/2],
relbar,
- pop,
- { "right", chartwo.width - charone.width },
- { "down", -size/2 },
+ popcommand,
+ rightcommand[chartwo.width - charone.width],
+ upcommand[size/2],
rightarrow,
}
}
@@ -325,10 +318,12 @@ local function accent_to_extensible(target,newchr,original,oldchr,height,depth,s
height = height or 0
depth = depth or 0
end
- local correction = swap and { "down", (olddata.height or 0) - height } or { "down", olddata.height + (offset or 0)}
+ local oldheight = olddata.height or 0
+ local correction = swap and
+ downcommand[oldheight - height]
+ or downcommand[oldheight + (offset or 0)]
local newdata = {
- commands = { correction, { "slot", 1, oldchr } },
- -- commands = { correction, { "slot", 0, oldchr } },
+ commands = { correction, charcommand[oldchr] },
width = olddata.width,
height = height,
depth = depth,
@@ -340,14 +335,12 @@ local function accent_to_extensible(target,newchr,original,oldchr,height,depth,s
local oldnextdata = characters[nextglyph]
if oldnextdata then
local newnextdata = {
- commands = { correction, { "slot", 1, nextglyph } },
- -- commands = { correction, { "slot", 0, nextglyph } },
+ commands = { correction, charcommand[nextglyph] },
width = oldnextdata.width,
height = height,
depth = depth,
}
--- local newnextglyph = addprivate(target,formatters["M-N-%H"](nextglyph),newnextdata)
- local newnextglyph = addprivate(target,nil,newnextdata)
+ local newnextglyph = addprivate(target,formatters["M-N-%H"](nextglyph),newnextdata)
newdata.next = newnextglyph
local nextnextglyph = oldnextdata.next
if nextnextglyph == nextglyph then
@@ -372,14 +365,12 @@ local function accent_to_extensible(target,newchr,original,oldchr,height,depth,s
local olddata = characters[oldglyph]
if olddata then
local newdata = {
- commands = { correction, { "slot", 1, oldglyph } },
- -- commands = { correction, { "slot", 0, oldglyph } },
+ commands = { correction, charcommand[oldglyph] },
width = olddata.width,
height = height,
depth = depth,
}
--- hvi.glyph = addprivate(target,formatters["M-H-%H"](oldglyph),newdata)
- hvi.glyph = addprivate(target,nil,newdata)
+ hvi.glyph = addprivate(target,formatters["M-H-%H"](oldglyph),newdata)
else
report_fallbacks("error in fallback: no valid horiz_variants, slot %X, index %i",oldglyph,i)
end
@@ -393,15 +384,16 @@ end
virtualcharacters[0x203E] = function(data)
local target = data.target
- local height, depth = 0, 0
--- local mathparameters = target.mathparameters
--- if mathparameters then
--- height = mathparameters.OverbarVerticalGap
--- depth = mathparameters.UnderbarVerticalGap
--- else
+ local height = 0
+ local depth = 0
+ -- local mathparameters = target.mathparameters
+ -- if mathparameters then
+ -- height = mathparameters.OverbarVerticalGap
+ -- depth = mathparameters.UnderbarVerticalGap
+ -- else
height = target.parameters.xheight/4
depth = height
--- end
+ -- end
return accent_to_extensible(target,0x203E,data.original,0x0305,height,depth,nil,nil,0x203E)
end
@@ -431,7 +423,7 @@ local function spacefraction(data,fraction)
local width = fraction * data.target.parameters.space
return {
width = width,
- commands = { { "right", width } }
+ commands = { rightcommand[width] }
}
end
@@ -439,7 +431,7 @@ local function charfraction(data,char)
local width = data.target.characters[char].width
return {
width = width,
- commands = { { "right", width } }
+ commands = { rightcommand[width] }
}
end
@@ -447,7 +439,7 @@ local function quadfraction(data,fraction)
local width = fraction * data.target.parameters.quad
return {
width = width,
- commands = { { "right", width } }
+ commands = { rightcommand[width] }
}
end
@@ -527,9 +519,8 @@ local function smashed(data,unicode,optional)
local shift = oldchar.height - height
local newchar = {
commands = {
- { "down", shift },
- { "slot", 0, unicode },
--- { "char", unicode },
+ downcommand[shift],
+ charcommand[unicode],
},
height = height,
width = oldchar.width,
@@ -607,11 +598,11 @@ local function actuarian(data)
width = basewidth + 4 * linewidth,
unicode = 0x20E7,
commands = {
- { "right", 2 * linewidth },
- { "down", - baseheight - 3 * linewidth },
+ rightcommand[2 * linewidth],
+ downcommand[- baseheight - 3 * linewidth],
{ "rule", linewidth, basewidth + 4 * linewidth },
- { "right", -linewidth },
- { "down", baseheight + 4 * linewidth },
+ leftcommand[linewidth],
+ downcommand[baseheight + 4 * linewidth],
{ "rule", baseheight + 5 * linewidth, linewidth },
},
}
@@ -629,11 +620,11 @@ local function equals(data,unicode,snippet,advance,n) -- mathpair needs them
unicode = unicode,
width = n*basechar.width + (n-1)*advance,
commands = {
- { "char", snippet },
- { "right", advance },
- { "char", snippet },
- n > 2 and { "right", advance } or nil,
- n > 2 and { "char", snippet } or nil,
+ charcommand[snippet],
+ rightcommand[advance],
+ charcommand[snippet],
+ n > 2 and rightcommand[advance] or nil,
+ n > 2 and charcommand[snippet] or nil,
},
}
end
@@ -657,11 +648,43 @@ virtualcharacters[0x2980] = function(data) return equals(data,0x2980,0x007C,-1/8
-- height = height, -- we cheat (no time now)
-- depth = depth, -- we cheat (no time now)
-- commands = {
--- { "down", - height/2 }, -- sort of works
--- { "char", 0x003D },
--- { "right", -width },
--- { "down", height }, -- sort of works
--- { "char", 0x003D },
+-- upcommand[height/2], -- sort of works
+-- charcommand[0x003D],
+-- leftcommand[width],
+-- downcommand[height], -- sort of works
+-- charcommand[0x003D],
-- },
-- }
-- end
+
+-- lucida needs this
+
+virtualcharacters[0x305] = function(data)
+ local target = data.target
+ local height = target.parameters.xheight/8
+ local width = target.parameters.emwidth/2
+ local depth = height
+ local used = 0.8 * width
+ return {
+ width = width,
+ height = height,
+ depth = depth,
+ commands = { { "rule", height, width } },
+ horiz_variants = {
+ {
+ advance = width,
+ ["end"] = used,
+ glyph = 0x305,
+ start = 0,
+ },
+ {
+ advance = width,
+ ["end"] = 0,
+ extender = 1,
+ glyph = 0x305,
+ start = used,
+ },
+ }
+ }
+end
+
diff --git a/tex/context/base/mkiv/math-fen.mkiv b/tex/context/base/mkiv/math-fen.mkiv
index a32ea410e..6c6724bf5 100644
--- a/tex/context/base/mkiv/math-fen.mkiv
+++ b/tex/context/base/mkiv/math-fen.mkiv
@@ -65,14 +65,19 @@
% we need the direct use of \Udelimiter because of { etc
-\newconditional\c_math_fenced_mirror \settrue\c_math_fenced_mirror
+\newconditional\c_math_fenced_mirror \settrue \c_math_fenced_mirror
+\newconditional\c_math_fenced_sized \setfalse\c_math_fenced_sized
\unexpanded\def\math_fenced_inject#1#2#3#4%
{\ifx#1\empty
#2.%
\else
\edef\p_mathclass{\mathfenceparameter\c!mathclass}%
- \edef\p_factor{\mathfenceparameter\c!factor}%
+ \ifconditional\c_math_fenced_sized
+ \let\p_factor\v!fixed
+ \else
+ \edef\p_factor{\mathfenceparameter\c!factor}%
+ \fi
\ifx\p_factor\empty
\ifx\p_mathclass\empty
#2%
@@ -97,7 +102,11 @@
\s!axis
% #2%
\else
- \scratchdimen\dimexpr\p_factor\bodyfontsize/2\relax
+ \ifx\p_factor\v!fixed
+ \scratchdimen\scaledpoint
+ \else
+ \scratchdimen\dimexpr\p_factor\bodyfontsize/2\relax
+ \fi
#3%
\s!height\scratchdimen
\s!depth\scratchdimen
@@ -121,16 +130,14 @@
\mathfenceparameter\c!left
\fi}%
\math_fenced_color_push
- % \normalleft\ifx\p_left\empty.\else\Udelimiter\plusfour\fam\p_left\relax\fi
\math_fenced_inject\p_left\normalleft\Uleft\plusfour
\math_fenced_color_pop}
\def\math_fenced_middle
{\edef\p_middle
- {\mathfenceparameter\c!middle}%
+ {\mathfenceparameter\c!middle}%
\mskip\thinmuskip
\math_fenced_color_push
- % \normalmiddle\ifx\p_middle\empty.\else\Udelimiter\plusfour\fam\p_middle\relax\fi
\math_fenced_inject\p_middle\normalmiddle\Umiddle\plusfour
\math_fenced_color_pop
\mskip\thinmuskip}
@@ -147,7 +154,6 @@
\mathfenceparameter\c!right
\fi}%
\math_fenced_color_push
- % \normalright \ifx\p_right\empty.\else\Udelimiter\plusfive\fam\p_right\relax\fi
\math_fenced_inject\p_right\normalright\Uright\plusfive
\math_fenced_color_pop}
@@ -194,16 +200,60 @@
\edef\currentmathfence{#1}%
\dosingleempty\math_fenced_fenced_indeed}
-\unexpanded\def\math_fenced_fenced_indeed[#1]#2%
+\def\math_fenced_force_size#1#2%
+ {\attribute\mathsizeattribute\numexpr#1*\plushundred+#2\relax}
+
+% \unexpanded\def\math_fenced_fenced_indeed[#1]#2%
+% {\iffirstargument\setupcurrentmathfence[#1]\fi
+% \math_fenced_fenced_common
+% \edef\p_size{\mathfenceparameter\c!size}%
+% \ifx\p_size\empty
+% \setfalse\c_math_fenced_sized
+% \else
+% \settrue\c_math_fenced_sized
+% \math_fenced_force_size\bigmathdelimitervariant\p_size
+% \fi
+% \math_fenced_left
+% #2%
+% \math_fenced_right
+% \stopusemathstyleparameter
+% \endgroup
+% \advance\c_math_fenced_nesting\minusone}
+
+\unexpanded\def\math_fenced_fenced_indeed[#1]%
{\iffirstargument\setupcurrentmathfence[#1]\fi
\math_fenced_fenced_common
- \math_fenced_left
- #2%
- \math_fenced_right
- \stopusemathstyleparameter
+ \edef\p_size{\mathfenceparameter\c!size}%
+ \ifx\p_size\empty
+ \expandafter\math_fenced_fenced_indeed_adapt
+ \else
+ \expandafter\math_fenced_fenced_indeed_fixed
+ \fi}
+
+\unexpanded\def\math_fenced_fenced_indeed_finish
+ {\stopusemathstyleparameter
\endgroup
\advance\c_math_fenced_nesting\minusone}
+\unexpanded\def\math_fenced_fenced_indeed_fixed#1%
+ {\math_fenced_force_size\bigmathdelimitervariant\p_size
+ \settrue\c_math_fenced_sized
+ \math_fenced_left
+ \setfalse\c_math_fenced_sized
+ #1%
+ \settrue\c_math_fenced_sized
+ \math_fenced_right
+ \setfalse\c_math_fenced_sized
+ \math_fenced_fenced_indeed_finish}
+
+\unexpanded\def\math_fenced_fenced_indeed_adapt#1%
+ {\setfalse\c_math_fenced_sized
+ \math_fenced_left
+ #1%
+ \setfalse\c_math_fenced_sized
+ \math_fenced_right
+ \math_fenced_fenced_indeed_finish}
+
\appendtoks
\let\fenced\math_fenced_fenced
\to \everymathematics
@@ -440,31 +490,31 @@
\installmathfencepair \letteropenbrace \Lbrace \letterclosebrace \Rbrace % as we escape in mp textexts
-\installmathfencepair . \Lnothing . \Rnothing
-\installmathfencepair . \Rnothingmirrored . \Lnothingmirrored
+\installmathfencepair . \Lnothing . \Rnothing
+\installmathfencepair . \Rnothingmirrored . \Lnothingmirrored
-\installmathfencepair [ \Lbracket ] \Rbracket
-\installmathfencepair ] \Rbracketmirrored [ \Lbracketmirrored
+\installmathfencepair [ \Lbracket ] \Rbracket
+\installmathfencepair ] \Rbracketmirrored [ \Lbracketmirrored
-\installmathfencepair ( \Lparenthesis ) \Rparenthesis
-\installmathfencepair ) \Rparentmirrored ( \Lparentmirrored
+\installmathfencepair ( \Lparenthesis ) \Rparenthesis
+\installmathfencepair ) \Rparenthesismirrored ( \Lparenthesismirrored
-\installmathfencepair < \Langle > \Rangle
-\installmathfencepair > \Ranglemirrored < \Langlemirrored
+\installmathfencepair < \Langle > \Rangle
+\installmathfencepair > \Ranglemirrored < \Langlemirrored
-\installmathfencepair / \Lsolidus / \Rsolidus
-%installmathfencepair / \Rsolidusmirrored / \Lsolidusmirrored
+\installmathfencepair / \Lsolidus / \Rsolidus
+%installmathfencepair / \Rsolidusmirrored / \Lsolidusmirrored
-\installmathfencepair | \Lbar | \Rbar
-%installmathfencepair | \Rbarmirrored | \Lbarmirrored
+\installmathfencepair | \Lbar | \Rbar
+%installmathfencepair | \Rbarmirrored | \Lbarmirrored
-\installmathfencepair ⌊ \Lfloor ⌋ \Rfloor
-\installmathfencepair ⌋ \Rfloormirrored ⌊ \Lfloormirrored
-\installmathfencepair ⌈ \Lceiling ⌉ \Rceiling
-\installmathfencepair ⌉ \Rceilingmirrored ⌈ \Lceilingmirrored
+\installmathfencepair ⌊ \Lfloor ⌋ \Rfloor
+\installmathfencepair ⌋ \Rfloormirrored ⌊ \Lfloormirrored
+\installmathfencepair ⌈ \Lceiling ⌉ \Rceiling
+\installmathfencepair ⌉ \Rceilingmirrored ⌈ \Lceilingmirrored
-\installmathfencepair ⟨ \Langle ⟩ \Rangle
-\installmathfencepair ⟩ \Ranglemirrored ⟨ \Langlemirrored
+\installmathfencepair ⟨ \Langle ⟩ \Rangle
+\installmathfencepair ⟩ \Ranglemirrored ⟨ \Langlemirrored
\installmathfencepair ⟪ \Ldoubleangle ⟫ \Rdoubleangle
\installmathfencepair ⟫ \Rdoubleanglemirrored ⟪ \Ldoubleanglemirrored
@@ -475,10 +525,10 @@
\installmathfencepair ⦀ \Ltriplebar ⦀ \Rtriplebar
%installmathfencepair ⦀ \Rtriplebarmirrored ⦀ \Ltriplebarmirrored
-% \installmathfencepair { \Lbrace } \Rbrace
-% \installmathfencepair } \Rbracemirrored { \Lbracemirrored
+% \installmathfencepair { \Lbrace } \Rbrace
+% \installmathfencepair } \Rbracemirrored { \Lbracemirrored
-\installmathfencepair ⦗ \Linterv ⦘ \Rinterv
+\installmathfencepair ⦗ \Linterval ⦘ \Rinterval
\appendtoks
\ignorediscretionaries % so $\mtext{a|b}$ works, this is ok because it's an \hbox
@@ -591,7 +641,7 @@
\ifcase\bigmathdelimitermethod
\math_fenced_step#2\relax
\or
- \attribute\mathsizeattribute\numexpr\bigmathdelimitervariant*\plushundred+#1\relax
+ \math_fenced_force_size\bigmathdelimitervariant{#1}\relax
\math_fenced_step#2\relax
\else
\math_fenced_step#2{\vpack to\csname\??mathbig\number#1\endcsname\bodyfontsize{}}%
@@ -621,7 +671,7 @@
\unexpanded\def\mathdelimiterstep#1#2%
{\begingroup
- \attribute\mathsizeattribute\numexpr\plushundred+#1\relax
+ \math_fenced_force_size\plusone{#1}%
\math_fenced_step#2\relax
\endgroup}
diff --git a/tex/context/base/mkiv/math-frc.lua b/tex/context/base/mkiv/math-frc.lua
index 5c4879527..190c36410 100644
--- a/tex/context/base/mkiv/math-frc.lua
+++ b/tex/context/base/mkiv/math-frc.lua
@@ -28,8 +28,8 @@ end)
local ctx_normalatop = context.normalatop
local ctx_normalover = context.normalover
-local function mathfraction(how,left,right,width) -- of course we could use the scanners directly here which
- if how == v_no then -- is faster but also less abstract ... maybe some day
+local function mathfraction(how,left,right,width)
+ if how == v_no then
if left == 0x002E and right == 0x002E then
ctx_normalatop()
else
diff --git a/tex/context/base/mkiv/math-frc.mkiv b/tex/context/base/mkiv/math-frc.mkiv
index 9a5ce62b0..97107a6bf 100644
--- a/tex/context/base/mkiv/math-frc.mkiv
+++ b/tex/context/base/mkiv/math-frc.mkiv
@@ -611,6 +611,46 @@
% \unexpanded\def\ShowMathFractions#1#2%
% {\mathematics{x+\tfrac{#1}{#2}+1+\frac{#1}{#2}+2+\sfrac{#1}{#2}+g}}
+%D More fracking (for Alan):
+
+\def\s!vfrac{vfrac}
+
+\unexpanded\def\math_frac_colored_vulgar#1#2%
+ {\savecolor
+ \colo_helpers_activate\p_math_fractions_color
+ {\restorecolor#1}\Uskewed/{\restorecolor#2}}
+
+\unexpanded\def\math_frac_normal_vulgar#1#2%
+ {{#1}\Uskewed/{#2}}
+
+\unexpanded\def\vfrac#1#2%
+ {\bgroup
+ \edef\p_math_fractions_color{\namedmathfractionparameter\s!vfrac\c!color}%
+ \ifx\p_math_fractions_color\empty
+ \expandafter\math_frac_normal_vulgar
+ \else
+ \expandafter\math_frac_colored_vulgar
+ \fi
+ {#1}%
+ {#2}%
+ \egroup}
+
+\appendtoks
+ \edef\p_hfactor{\namedmathfractionparameter\s!vfrac\c!hfactor}%
+ \edef\p_vfactor{\namedmathfractionparameter\s!vfrac\c!vfactor}%
+ \Umathskewedfractionhgap\textstyle \p_hfactor\fontemwidth \mathstylefont\textstyle
+ \Umathskewedfractionhgap\scriptstyle \p_hfactor\fontemwidth \mathstylefont\scriptstyle
+ \Umathskewedfractionhgap\scriptscriptstyle\p_hfactor\fontemwidth \mathstylefont\scriptscriptstyle
+ \Umathskewedfractionvgap\textstyle \p_vfactor\fontexheight\mathstylefont\textstyle
+ \Umathskewedfractionvgap\scriptstyle \p_vfactor\fontexheight\mathstylefont\scriptstyle
+ \Umathskewedfractionvgap\scriptscriptstyle\p_vfactor\fontexheight\mathstylefont\scriptscriptstyle
+\to \everysetupmathfraction
+
+\setupmathfraction
+ [\s!vfrac]
+ [\c!hfactor=.2,
+ \c!vfactor=.1]
+
\protect \endinput
% I have no clue what \mthfrac and \mthsqrt are supposed to do but
@@ -660,7 +700,7 @@
% \unexpanded\def\mthfrac#1#2#3{[mthfrac: #1 #2 #3]}
% \unexpanded\def\mthsqrt#1#2#3{[mthsqrt: #1 #2 #3]}
-% used for prototypine \Uskewed
+% used for prototyping \Uskewed
%
% \unexpanded\def\skewedfractiona#1#2{%
% \raise
diff --git a/tex/context/base/mkiv/math-inc.lua b/tex/context/base/mkiv/math-inc.lua
new file mode 100644
index 000000000..010d29a35
--- /dev/null
+++ b/tex/context/base/mkiv/math-inc.lua
@@ -0,0 +1,87 @@
+if not modules then modules = { } end modules ['back-inc'] = {
+ version = 1.001,
+ comment = "companion to back-exp.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is an experiment. If it's really useful then I'll make a more efficient
+-- local export facility.
+
+local tonumber, next = tonumber, next
+local utfbyte, utfchar, utfsplit = utf.byte, utf.char, utf.split
+local match, gsub = string.match, string.gsub
+local nspaces = string.nspaces
+local concat = table.concat
+local xmltext = xml.text
+local undent = buffers.undent
+
+local f_entity = string.formatters["&x%X;"]
+local f_blob = string.formatters['<?xml version="2.0"?>\n\n<!-- formula %i -->\n\n%s']
+
+local all = nil
+local back = nil
+
+local function unmath(s)
+ local t = utfsplit(s)
+ for i=1,#t do
+ local ti = t[i]
+ local bi = utfbyte(ti)
+ if bi > 0xFFFF then
+ local ch = back[bi]
+ t[i] = ch and utfchar(ch) or f_entity(bi)
+ end
+ end
+ s = concat(t)
+ return s
+end
+
+local function beautify(s)
+ local b = match(s,"^( *)<m:math")
+ local e = match(s,"( *)</m:math>%s*$")
+ if b and e then
+ b = #b
+ e = #e
+ if e > b then
+ s = undent(nspaces[e-b] .. s)
+ elseif e < b then
+ s = undent((gsub(s,"^( *)",nspaces[b-e])))
+ end
+ end
+ return s
+end
+
+local function getblob(n)
+ if all == nil then
+ local name = file.nameonly(tex.jobname)
+ local full = name .. "-export/" .. name .. "-raw.xml"
+ if lfs.isfile(full) then
+ all = { }
+ back = { }
+ local root = xml.load(full)
+ for c in xml.collected(root,"formulacontent") do
+ local index = tonumber(c.at.n)
+ all[index] = f_blob(index,beautify(xmltext(c,"math") or ""))
+ end
+ local it = mathematics.alphabets.regular.it
+ for k, v in next, it.digits do back[v] = k end
+ for k, v in next, it.ucletters do back[v] = k end
+ for k, v in next, it.lcletters do back[v] = k end
+ else
+ all = false
+ end
+ end
+ if all == false then
+ return ""
+ end
+ return unmath(all[n] or "")
+end
+
+interfaces.implement {
+ name = "xmlformulatobuffer",
+ arguments = { "integer", "string" },
+ actions = function(n,target)
+ buffers.assign(target,getblob(n))
+ end
+}
diff --git a/tex/context/base/mkiv/math-inc.mkiv b/tex/context/base/mkiv/math-inc.mkiv
new file mode 100644
index 000000000..2821580cb
--- /dev/null
+++ b/tex/context/base/mkiv/math-inc.mkiv
@@ -0,0 +1,69 @@
+%D \module
+%D [ file=math-inc,
+%D version=2018.06.23,
+%D title=\CONTEXT\ Math Macros,
+%D subtitle=XML inclusion,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Math Macros / XML inclusion}
+
+\registerctxluafile{math-inc}{}
+
+%D I had some doubt about including this in \CONTEXT\ but it might serve some users
+%D anyway. It's always the question to what extent one can be really roundtrip. I
+%D might improve it when I need it.
+
+% Talking about creating from a source ... June Lee's transcription of
+% Close to You by Jacob Collier is an amazing example:
+%
+% https://www.youtube.com/watch?v=hdBVN-HMuqI
+
+\unprotect
+
+\definesymbol[mmlattachment][{\infofont\darkred mml}]
+\definesymbol[mmlcomment] [{\infofont\darkblue mml}]
+
+\unexpanded\def\lxml_add_mml_blob#1#2%
+ {\relax
+ \clf_xmlformulatobuffer\number\c_strc_formulas_n{temp-xml-export}%
+ #2%
+ [\c!symbol=#1,%
+ \c!space=\v!yes,%
+ \c!buffer=temp-xml-export,%
+ \c!name={formula-\number\c_strc_formulas_n.xml}]%
+ \relax}
+
+\unexpanded\def\xmlattachmml
+ {\iftrialtypesetting \else \ifexporting \iflocation
+ \dostarttagged\t!ignore\empty
+ \lxml_add_mml_blob{mmlattachment}\attachment
+ \dostoptagged
+ \fi \fi \fi}
+
+\unexpanded\def\xmlcommentmml
+ {\iftrialtypesetting \else \ifexporting \iflocation
+ \dostarttagged\t!ignore\empty
+ \lxml_add_mml_blob{mmlcomment}\comment
+ \dostoptagged
+ \fi \fi \fi}
+
+%D This kind of feature creep is not yet configurable, nor documented.
+
+\unexpanded\def\xmladdmmlsource
+ {\iftrialtypesetting \else \ifexporting \iflocation
+ \dostarttagged\t!ignore\empty
+ \inleftmargin{%
+ \lxml_add_mml_blob{mmlattachment}\attachment
+ \quad
+ \lxml_add_mml_blob{mmlcomment}\comment
+ }%
+ \dostoptagged
+ \fi \fi \fi}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/math-ini.lua b/tex/context/base/mkiv/math-ini.lua
index b79ef8c8c..7a8419702 100644
--- a/tex/context/base/mkiv/math-ini.lua
+++ b/tex/context/base/mkiv/math-ini.lua
@@ -36,8 +36,8 @@ local report_math = logs.reporter("mathematics","initializing")
mathematics = mathematics or { }
local mathematics = mathematics
-mathematics.extrabase = 0xFE000 -- here we push some virtuals
-mathematics.privatebase = 0xFF000 -- here we push the ex
+mathematics.extrabase = fonts.privateoffsets.mathextrabase -- here we push some virtuals
+mathematics.privatebase = fonts.privateoffsets.mathbase -- here we push the ex
local unsetvalue = attributes.unsetvalue
local allocate = utilities.storage.allocate
@@ -289,7 +289,8 @@ function mathematics.define(family)
local data = characters.data
for unicode, character in sortedhash(data) do
local symbol = character.mathsymbol
- local mset, dset = true, true
+ local mset = true
+ local dset = true
if symbol then
local other = data[symbol]
local class = other.mathclass
@@ -641,7 +642,7 @@ function mathematics.big(tfmdata,unicode,n,method)
end
end
end
- else
+ elseif method == 3 then
local size = 1.33^n
if method == 4 then
size = tfmdata.parameters.size * size
diff --git a/tex/context/base/mkiv/math-ini.mkiv b/tex/context/base/mkiv/math-ini.mkiv
index 17d900d74..50da1a400 100644
--- a/tex/context/base/mkiv/math-ini.mkiv
+++ b/tex/context/base/mkiv/math-ini.mkiv
@@ -123,9 +123,12 @@
\definesystemattribute[mathbidi] [public]
\definesystemattribute[mathdomain] [public]
\definesystemattribute[mathcollapsing] [public]
+\definesystemattribute[mathunstack] [public]
\definesystemattribute[displaymath] [public]
+\mathflattenmode 31
+
\appendtoks
\attribute\mathmodeattribute\plusone
\to \everydisplay
@@ -217,18 +220,20 @@
\unexpanded\def\startmathematics % no grouping, if ever then also an optional second
{\doifelsenextoptionalcs\math_mathematics_start_yes\math_mathematics_start_nop}
+\installmacrostack\currentmathematics
+
\unexpanded\def\math_mathematics_start_yes[#1]%
- {\pushmacro\currentmathematics
+ {\push_macro_currentmathematics
\edef\currentmathematics{#1}% check for valid
\the\everyswitchmathematics}
\unexpanded\def\math_mathematics_start_nop
- {\pushmacro\currentmathematics
+ {\push_macro_currentmathematics
\let\currentmathematics\empty
\the\everyswitchmathematics}
\unexpanded\def\stopmathematics
- {\popmacro\currentmathematics
+ {\pop_macro_currentmathematics
\the\everyswitchmathematics}
\definemathematics[\v!default] % not needed, but nicer when nesting back to normal
@@ -734,7 +739,6 @@
%
% \def\math_op{\ifx\nexttoken\bgroup\else\nexttoken\egroup\fi}
-
% this one too: \letvalue{\??mathcodecommand op}\mathop ?
\unexpanded\def\normalmbox
@@ -750,17 +754,15 @@
{\ifmmode\normalmbox\else\normalhbox\fi}
\unexpanded\def\enablembox
- {\appendtoks\math_enable_mbox\to \everymathematics}
- {\everymathematics\expandafter{\the\everymathematics\math_enable_mbox}}
+ {\toksapp\everymathematics{\math_enable_mbox}}
\def\math_enable_mbox
- {\ifdefined\normalhbox\else\let\normalhbox\hbox\fi % ?
- \let\hbox\mbox}
+ {\let\hbox\mbox}
\unexpanded\def\snappedmath#1% sort of \struttedbox
{\dontleavehmode
\begingroup
- \setbox\scratchbox\hbox\bgroup
+ \setbox\scratchbox\normalhbox\bgroup
\startimath#1\stopimath
\egroup
\ht\scratchbox\strutht
@@ -1077,8 +1079,8 @@
% most math fonts have messed up primes, just test this: $\prime^{\prime^{\prime}}$
-{ \catcode\circumflexasciicode\othercatcode \global\let\othercircumflextoken ^ }
-{ \catcode\circumflexasciicode\superscriptcatcode \global\let\superscriptcircumflextoken^ }
+{ \catcode\circumflexasciicode\othercatcode \glet\othercircumflextoken ^ }
+{ \catcode\circumflexasciicode\superscriptcatcode \glet\superscriptcircumflextoken^ }
\ifdefined \prime \else
\Umathchardef\prime "0 "0 "2032
@@ -1273,9 +1275,13 @@
%D Memory saver:
+\def\math_basics_check_compact
+ {\doifelse{\mathematicsparameter\c!compact}\v!yes
+ \enabledirectives\disabledirectives[math.virtual.optional]}
+
\appendtoks
\ifx\currentmathematics\empty
- \doifelse{\mathematicsparameter\c!compact}\v!yes\enabledirectives\disabledirectives[math.virtual.optional]%
+ \math_basics_check_compact % less tracing
\fi
\to \everysetupmathematics
@@ -1311,18 +1317,31 @@
%D \HL
%D \stoptabulate
+% We will use proper constants when we go numbers instead of XXX.
+
\newconditional\c_math_right_to_left
+\installcorenamespace{mathaligndirection}
+
+\setvalue{\??mathaligndirection r2l}{\settrue\c_math_right_to_left}
+\setvalue{\??mathaligndirection\v!righttoleft}{\settrue\c_math_right_to_left}
+
\appendtoks
- \doifelse{\mathematicsparameter\c!align}{r2l}\settrue\setfalse\c_math_right_to_left
+ \ifcsname\??mathaligndirection\mathematicsparameter\c!align\endcsname
+ \lastnamedcs
+ \else
+ \setfalse\c_math_right_to_left
+ \fi
\to \everyswitchmathematics
\unexpanded\def\math_basics_synchronize_direction
- {\mathdir T\ifconditional\c_math_right_to_left R\else L\fi T}
+ {\mathdirection\ifconditional\c_math_right_to_left\directionrighttoleft\else\directionlefttoright\fi}
+
+% Not \everymathematics as it comes too late and I'm not in the mood for a mixed mode
+% kludge now (should be a property of beginmath nodes and passed to callbacks).
\appendtoks
\math_basics_synchronize_direction
-%to \everymathematics % comes too late and I'm not in the mood for a mixed mode kludge now (should be a property of beginmath nodes and passed to callbacks)
\to \everyswitchmathematics
% experimental (needed for an article)
@@ -1337,11 +1356,6 @@
\letvalue{\??mathbidi\v!yes}\math_bidi_enable
\letvalue{\??mathbidi\v!no }\math_bidi_disable
-% \appendtoks
-% \edef\p_bidi{\mathematicsparameter\c!bidi}%
-% \csname\??mathbidi\ifcsname\??mathbidi\p_bidi\endcsname\p_bidi\else\v!no\fi\endcsname
-% \to \everysetupmathematics
-
\appendtoks
\edef\p_bidi{\mathematicsparameter\c!bidi}% still needed ?
\ifcsname\??mathbidi\p_bidi\endcsname\lastnamedcs\else\math_bidi_disable\fi
@@ -1434,7 +1448,7 @@
\def\math_collapsing_initialize
{\ifnum\c_math_collapsing_attribute=\attributeunsetvalue \else
\clf_initializemathcollapsing % one time
- \global\let\math_collapsing_initialize\relax
+ \glet\math_collapsing_initialize\relax
\fi}
\appendtoks
@@ -1471,7 +1485,7 @@
\def\math_italics_initialize
{\ifnum\c_math_italics_attribute=\attributeunsetvalue \else
\clf_initializemathitalics % one time
- \global\let\math_italics_initialize\relax
+ \glet\math_italics_initialize\relax
\fi}
\appendtoks
@@ -1511,7 +1525,7 @@
\def\math_kernpairs_initialize
{\ifnum\c_math_kernpairs_attribute=\attributeunsetvalue \else
\clf_initializemathkernpairs % one time
- \global\let\math_kernpairs_initialize\relax
+ \glet\math_kernpairs_initialize\relax
\fi}
\appendtoks
@@ -2343,7 +2357,7 @@
% \c_math_styles_state_cramped\zerocount
% \c_math_styles_state_size \zerocount
% \rawprocesscommacommand[\m_math_style_asked]\math_style_collect
-% \global\expandafter\let\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}%
+% \expandafter\glet\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}%
% \csname\??mathstylecache\m_math_style_asked\endcsname}
\def\math_style_set_indeed
@@ -2365,7 +2379,7 @@
\c_math_styles_state_cramped\zerocount
\c_math_styles_state_size \zerocount
\rawprocesscommacommand[\m_math_style_asked]\math_style_collect
- \global\expandafter\let\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}%
+ \expandafter\glet\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}%
\csname\??mathstylecache\m_math_style_asked\endcsname}
\letvalue{\??mathstyle \??mathstyle }\math_style_set_mathstyle_mathstyle % still needed?
@@ -2468,10 +2482,12 @@
% I need to decide:
%
-%mathscriptboxmode\zerocount % no kerning
-%mathscriptboxmode\plusone % lists
-\mathscriptboxmode\plustwo % lists and boxes
-%mathscriptboxmode\plusthree % lists and boxes with \boundary=1 (also for testing and demo)
+%mathscriptboxmode \zerocount % no kerning
+%mathscriptboxmode \plusone % lists
+\mathscriptboxmode \plustwo % lists and boxes
+\mathscriptcharmode \plusone % lists and boxes
+%mathscriptboxmode \plusthree % lists and boxes with \boundary=1 (also for testing and demo)
+\mathrulethicknessmode\plusone % adaptive
\unexpanded\def\mathtext {\mathortext{\math_text_choice_font\relax}\hbox}
\unexpanded\def\mathword {\mathortext{\math_text_choice_word\relax}\hbox}
@@ -2529,7 +2545,7 @@
% this can become an option:
\unexpanded\def\math_display_align_hack % I don't like the global, maybe we should push and pop
- {\global\let\math_display_align_hack_indeed\math_display_align_hack_remove_skip
+ {\glet\math_display_align_hack_indeed\math_display_align_hack_remove_skip
\math_openup\displayopenupvalue % was \math_openup\jot
\everycr{\noalign{\math_display_align_hack_indeed}}}
@@ -2537,7 +2553,7 @@
{\ifdim\prevdepth>-\thousandpoint
\vskip\dimexpr-\lineskiplimit+\normallineskiplimit\relax
\fi
- \global\let\math_display_align_hack_indeed\math_display_align_hack_insert_penalty}
+ \glet\math_display_align_hack_indeed\math_display_align_hack_insert_penalty}
\def\math_display_align_hack_insert_penalty
{\penalty\interdisplaylinepenalty}
@@ -2767,7 +2783,7 @@
\def\math_domain_initialize
{\ifnum\c_math_domain_attribute=\attributeunsetvalue \else
\clf_initializemathdomain % one time
- \global\let\math_domain_initialize\relax
+ \glet\math_domain_initialize\relax
\fi}
\appendtoks
@@ -2791,7 +2807,7 @@
\installcorenamespace{mathrules}
-\unexpanded\def\enablemathrules{\global\letvalue{\??mathrules\fontclass}\plusone}
+\unexpanded\def\enablemathrules{\letgvalue{\??mathrules\fontclass}\plusone}
\appendtoks
\mathrulesmode\ifcsname\??mathrules\fontclass\endcsname
@@ -2802,6 +2818,70 @@
\mathrulesfam\zerocount
\to \everymathematics
+%D Maybe:
+
+% \starttabulate[|||c|c|]
+% \BC positive \BC negative \BC text \BC math \NC \NR
+% \NC \tex {f1} \tex {hairspace} \tex{,} \NC \tex {b1} \tex {neghairspace} \NC {\darkred\vl}\f1{\darkblue\vl} \NC ${\darkred\vl}\f1{\darkblue\vl}$ \NC \NR
+% \NC \tex {f2} \tex {thinspace} \tex{:} \NC \tex {b2} \tex {negthinspace} \tex{!} \NC {\darkred\vl}\f2{\darkblue\vl} \NC ${\darkred\vl}\f2{\darkblue\vl}$ \NC \NR
+% \NC \tex {f3} \tex {medspace} \tex{;} \NC \tex {b3} \tex {negmedspace} \NC {\darkred\vl}\f3{\darkblue\vl} \NC ${\darkred\vl}\f3{\darkblue\vl}$ \NC \NR
+% \NC \tex {f4} \tex {thickspace} \NC \tex {b4} \tex {negthickspace} \NC {\darkred\vl}\f4{\darkblue\vl} \NC ${\darkred\vl}\f4{\darkblue\vl}$ \NC \NR
+% \NC \tex {f5} \tex {enspace} \NC \tex {b5} \NC {\darkred\vl}\f5{\darkblue\vl} \NC ${\darkred\vl}\f5{\darkblue\vl}$ \NC \NR
+% \NC \tex {f6} \tex {emspace} \NC \tex {b6} \NC {\darkred\vl}\f6{\darkblue\vl} \NC ${\darkred\vl}\f6{\darkblue\vl}$ \NC \NR
+% \stoptabulate
+
+% \unexpanded\def\negenspace{\kern-.5\emwidth}
+% \unexpanded\def\negemspace{\kern- \emwidth}
+%
+% \unexpanded\def\math_f#1%
+% {\ifcase#1\or
+% \hairspace
+% \or
+% \thinspace
+% \or
+% \medspace
+% \or
+% \thickspace
+% \or
+% \enspace
+% \or
+% \emspace
+% \fi}
+%
+% \unexpanded\def\math_b#1%
+% {\ifcase#1\or
+% \neghairspace
+% \or
+% \negthinspace
+% \or
+% \negmedspace
+% \or
+% \negthickspace
+% \or
+% \negenspace
+% \or
+% \negemspace
+% \fi}
+%
+% \appendtoks
+% \let\f\math_f
+% \let\b\math_b
+% \to \everymathematics
+
+%D Experiment
+
+\unexpanded\def\math_scripts_stack
+ {\attribute\mathunstackattribute\attributeunsetvalue}
+
+\unexpanded\def\math_scripts_unstack
+ {\clf_enablescriptunstacking
+ \attribute\mathunstackattribute\plusone}
+
+\appendtoks
+ \let\stackscripts \math_scripts_stack
+ \let\unstackscripts\math_scripts_unstack
+\to \everymathematics
+
\protect \endinput
% % not used (yet)
diff --git a/tex/context/base/mkiv/math-noa.lua b/tex/context/base/mkiv/math-noa.lua
index 529837cfa..ea7583587 100644
--- a/tex/context/base/mkiv/math-noa.lua
+++ b/tex/context/base/mkiv/math-noa.lua
@@ -19,7 +19,7 @@ if not modules then modules = { } end modules ['math-noa'] = {
-- 20D6 -> 2190
-- 20D7 -> 2192
--- todo: most is math_char so we can have simple dedicated loops
+-- todo: most is mathchar_code so we can have simple dedicated loops
-- nota bene: uunderdelimiter uoverdelimiter etc are radicals (we have 5 types)
@@ -31,177 +31,184 @@ local insert, remove = table.insert, table.remove
local div = math.div
local bor, band = bit32.bor, bit32.band
-local fonts = fonts
-local nodes = nodes
-local node = node
-local mathematics = mathematics
-local context = context
-
-local otf = fonts.handlers.otf
-local otffeatures = fonts.constructors.features.otf
-local registerotffeature = otffeatures.register
-
-local privateattribute = attributes.private
-local registertracker = trackers.register
-local registerdirective = directives.register
-local logreporter = logs.reporter
-local setmetatableindex = table.setmetatableindex
-
-local colortracers = nodes.tracers.colors
-
-local trace_remapping = false registertracker("math.remapping", function(v) trace_remapping = v end)
-local trace_processing = false registertracker("math.processing", function(v) trace_processing = v end)
-local trace_analyzing = false registertracker("math.analyzing", function(v) trace_analyzing = v end)
-local trace_normalizing = false registertracker("math.normalizing", function(v) trace_normalizing = v end)
-local trace_collapsing = false registertracker("math.collapsing", function(v) trace_collapsing = v end)
-local trace_fixing = false registertracker("math.fixing", function(v) trace_foxing = v end)
-local trace_patching = false registertracker("math.patching", function(v) trace_patching = v end)
-local trace_goodies = false registertracker("math.goodies", function(v) trace_goodies = v end)
-local trace_variants = false registertracker("math.variants", function(v) trace_variants = v end)
-local trace_alternates = false registertracker("math.alternates", function(v) trace_alternates = v end)
-local trace_italics = false registertracker("math.italics", function(v) trace_italics = v end)
-local trace_kernpairs = false registertracker("math.kernpairs", function(v) trace_kernpairs = v end)
-local trace_domains = false registertracker("math.domains", function(v) trace_domains = v end)
-local trace_families = false registertracker("math.families", function(v) trace_families = v end)
-local trace_fences = false registertracker("math.fences", function(v) trace_fences = v end)
-
-local check_coverage = true registerdirective("math.checkcoverage", function(v) check_coverage = v end)
-
-local report_processing = logreporter("mathematics","processing")
-local report_remapping = logreporter("mathematics","remapping")
-local report_normalizing = logreporter("mathematics","normalizing")
-local report_collapsing = logreporter("mathematics","collapsing")
-local report_fixing = logreporter("mathematics","fixing")
-local report_patching = logreporter("mathematics","patching")
-local report_goodies = logreporter("mathematics","goodies")
-local report_variants = logreporter("mathematics","variants")
-local report_alternates = logreporter("mathematics","alternates")
-local report_italics = logreporter("mathematics","italics")
-local report_kernpairs = logreporter("mathematics","kernpairs")
-local report_domains = logreporter("mathematics","domains")
-local report_families = logreporter("mathematics","families")
-local report_fences = logreporter("mathematics","fences")
-
-local a_mathrendering = privateattribute("mathrendering")
-local a_exportstatus = privateattribute("exportstatus")
-
-local nuts = nodes.nuts
-local nodepool = nuts.pool
-local tonut = nuts.tonut
-local tonode = nuts.tonode
-local nutstring = nuts.tostring
-
-local setfield = nuts.setfield
-local setlink = nuts.setlink
-local setlist = nuts.setlist
-local setnext = nuts.setnext
-local setprev = nuts.setprev
-local setchar = nuts.setchar
-local setfam = nuts.setfam
-local setsubtype = nuts.setsubtype
-local setattr = nuts.setattr
-local setattrlist = nuts.setattrlist
-
-local getfield = nuts.getfield
-local getnext = nuts.getnext
-local getprev = nuts.getprev
-local getboth = nuts.getboth
-local getid = nuts.getid
-local getsubtype = nuts.getsubtype
-local getchar = nuts.getchar
-local getfont = nuts.getfont
-local getfam = nuts.getfam
-local getattr = nuts.getattr
-local getlist = nuts.getlist
-
-local getnucleus = nuts.getnucleus
-local getsub = nuts.getsub
-local getsup = nuts.getsup
-
-local setnucleus = nuts.setnucleus
-local setsub = nuts.setsub
-local setsup = nuts.setsup
-
-local flush_node = nuts.flush
-local copy_node = nuts.copy
-local slide_nodes = nuts.slide
-local set_visual = nuts.setvisual
-
-local mlist_to_hlist = nodes.mlist_to_hlist
-
-local font_of_family = node.family_font
-
-local new_kern = nodepool.kern
-local new_submlist = nodepool.submlist
-local new_noad = nodepool.noad
-local new_delimiter = nodepool.delimiter
-local new_fence = nodepool.fence
-
-local fonthashes = fonts.hashes
-local fontdata = fonthashes.identifiers
-local fontcharacters = fonthashes.characters
-local fontitalics = fonthashes.italics
-
-local variables = interfaces.variables
-local texsetattribute = tex.setattribute
-local texgetattribute = tex.getattribute
-local unsetvalue = attributes.unsetvalue
-local implement = interfaces.implement
-
-local v_reset = variables.reset
-
-local chardata = characters.data
-
-noads = noads or { } -- todo: only here
-local noads = noads
-
-noads.processors = noads.processors or { }
-local processors = noads.processors
-
-noads.handlers = noads.handlers or { }
-local handlers = noads.handlers
-
-local tasks = nodes.tasks
-local enableaction = tasks.enableaction
-local setaction = tasks.setaction
-
-local nodecodes = nodes.nodecodes
-local noadcodes = nodes.noadcodes
-local fencecodes = nodes.fencecodes
-
-local noad_ord = noadcodes.ord
-local noad_rel = noadcodes.rel
-local noad_bin = noadcodes.bin
-local noad_open = noadcodes.open
-local noad_close = noadcodes.close
-local noad_punct = noadcodes.punct
-local noad_opdisplaylimits = noadcodes.opdisplaylimits
-local noad_oplimits = noadcodes.oplimits
-local noad_opnolimits = noadcodes.opnolimits
-local noad_inner = noadcodes.inner
-
-local math_noad = nodecodes.noad -- attr nucleus sub sup
-local math_accent = nodecodes.accent -- attr nucleus sub sup accent
-local math_radical = nodecodes.radical -- attr nucleus sub sup left degree
-local math_fraction = nodecodes.fraction -- attr nucleus sub sup left right
-local math_subbox = nodecodes.subbox -- attr list
-local math_submlist = nodecodes.submlist -- attr list
-local math_char = nodecodes.mathchar -- attr fam char
-local math_textchar = nodecodes.mathtextchar -- attr fam char
-local math_delim = nodecodes.delim -- attr small_fam small_char large_fam large_char
------ math_style = nodecodes.style -- attr style
-local math_choice = nodecodes.choice -- attr display text script scriptscript
-local math_fence = nodecodes.fence -- attr subtype
-
-local left_fence_code = fencecodes.left
-local middle_fence_code = fencecodes.middle
-local right_fence_code = fencecodes.right
+local fonts = fonts
+local nodes = nodes
+local node = node
+local mathematics = mathematics
+local context = context
+
+local otf = fonts.handlers.otf
+local otffeatures = fonts.constructors.features.otf
+local registerotffeature = otffeatures.register
+
+local privateattribute = attributes.private
+local registertracker = trackers.register
+local registerdirective = directives.register
+local logreporter = logs.reporter
+local setmetatableindex = table.setmetatableindex
+
+local colortracers = nodes.tracers.colors
+
+local trace_remapping = false registertracker("math.remapping", function(v) trace_remapping = v end)
+local trace_processing = false registertracker("math.processing", function(v) trace_processing = v end)
+local trace_analyzing = false registertracker("math.analyzing", function(v) trace_analyzing = v end)
+local trace_normalizing = false registertracker("math.normalizing", function(v) trace_normalizing = v end)
+local trace_collapsing = false registertracker("math.collapsing", function(v) trace_collapsing = v end)
+local trace_fixing = false registertracker("math.fixing", function(v) trace_foxing = v end)
+local trace_patching = false registertracker("math.patching", function(v) trace_patching = v end)
+local trace_goodies = false registertracker("math.goodies", function(v) trace_goodies = v end)
+local trace_variants = false registertracker("math.variants", function(v) trace_variants = v end)
+local trace_alternates = false registertracker("math.alternates", function(v) trace_alternates = v end)
+local trace_italics = false registertracker("math.italics", function(v) trace_italics = v end)
+local trace_kernpairs = false registertracker("math.kernpairs", function(v) trace_kernpairs = v end)
+local trace_domains = false registertracker("math.domains", function(v) trace_domains = v end)
+local trace_families = false registertracker("math.families", function(v) trace_families = v end)
+local trace_fences = false registertracker("math.fences", function(v) trace_fences = v end)
+local trace_unstacking = false registertracker("math.unstack", function(v) trace_unstacking = v end)
+
+local check_coverage = true registerdirective("math.checkcoverage", function(v) check_coverage = v end)
+
+local report_processing = logreporter("mathematics","processing")
+local report_remapping = logreporter("mathematics","remapping")
+local report_normalizing = logreporter("mathematics","normalizing")
+local report_collapsing = logreporter("mathematics","collapsing")
+local report_fixing = logreporter("mathematics","fixing")
+local report_patching = logreporter("mathematics","patching")
+local report_goodies = logreporter("mathematics","goodies")
+local report_variants = logreporter("mathematics","variants")
+local report_alternates = logreporter("mathematics","alternates")
+local report_italics = logreporter("mathematics","italics")
+local report_kernpairs = logreporter("mathematics","kernpairs")
+local report_domains = logreporter("mathematics","domains")
+local report_families = logreporter("mathematics","families")
+local report_fences = logreporter("mathematics","fences")
+local report_unstacking = logreporter("mathematics","unstack")
+
+local a_mathrendering = privateattribute("mathrendering")
+local a_exportstatus = privateattribute("exportstatus")
+
+local nuts = nodes.nuts
+local nodepool = nuts.pool
+local tonut = nuts.tonut
+local nutstring = nuts.tostring
+
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local setchar = nuts.setchar
+local setfam = nuts.setfam
+local setsubtype = nuts.setsubtype
+local setattr = nuts.setattr
+local setattrlist = nuts.setattrlist
+local setwidth = nuts.setwidth
+local setheight = nuts.setheight
+local setdepth = nuts.setdepth
+
+local getfield = nuts.getfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getboth = nuts.getboth
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getchar = nuts.getchar
+local getfont = nuts.getfont
+local getfam = nuts.getfam
+local getattr = nuts.getattr
+local getlist = nuts.getlist
+local getwidth = nuts.getwidth
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
+
+local getnucleus = nuts.getnucleus
+local getsub = nuts.getsub
+local getsup = nuts.getsup
+
+local setnucleus = nuts.setnucleus
+local setsub = nuts.setsub
+local setsup = nuts.setsup
+
+local flush_node = nuts.flush
+local copy_node = nuts.copy
+local slide_nodes = nuts.slide
+local set_visual = nuts.setvisual
+
+local mlist_to_hlist = nuts.mlist_to_hlist
+
+local font_of_family = node.family_font
+
+local new_kern = nodepool.kern
+local new_submlist = nodepool.submlist
+local new_noad = nodepool.noad
+local new_delimiter = nodepool.delimiter
+local new_fence = nodepool.fence
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local fontcharacters = fonthashes.characters
+local fontitalics = fonthashes.italics
+
+local variables = interfaces.variables
+local texsetattribute = tex.setattribute
+local texgetattribute = tex.getattribute
+local unsetvalue = attributes.unsetvalue
+local implement = interfaces.implement
+
+local v_reset = variables.reset
+
+local chardata = characters.data
+
+noads = noads or { } -- todo: only here
+local noads = noads
+
+noads.processors = noads.processors or { }
+local processors = noads.processors
+
+noads.handlers = noads.handlers or { }
+local handlers = noads.handlers
+
+local tasks = nodes.tasks
+local enableaction = tasks.enableaction
+local setaction = tasks.setaction
+
+local nodecodes = nodes.nodecodes
+local noadcodes = nodes.noadcodes
+local fencecodes = nodes.fencecodes
+
+local ordnoad_code = noadcodes.ord
+local relnode_code = noadcodes.rel
+local binnoad_code = noadcodes.bin
+local opennoad_code = noadcodes.open
+local closenoad_code = noadcodes.close
+local punctnoad_code = noadcodes.punct
+local opdisplaylimitsnoad_code = noadcodes.opdisplaylimits
+local oplimitsnoad_code = noadcodes.oplimits
+local opnolimitsnoad_code = noadcodes.opnolimits
+local innernoad_code = noadcodes.inner
+
+local noad_code = nodecodes.noad -- attr nucleus sub sup
+local accent_code = nodecodes.accent -- attr nucleus sub sup accent
+local radical_code = nodecodes.radical -- attr nucleus sub sup left degree
+local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right
+local subbox_code = nodecodes.subbox -- attr list
+local submlist_code = nodecodes.submlist -- attr list
+local mathchar_code = nodecodes.mathchar -- attr fam char
+local mathtextchar_code = nodecodes.mathtextchar -- attr fam char
+local delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char
+----- style_code = nodecodes.style -- attr style
+local math_choice = nodecodes.choice -- attr display text script scriptscript
+local fence_code = nodecodes.fence -- attr subtype
+
+local leftfence_code = fencecodes.left
+local middlefence_code = fencecodes.middle
+local rightfence_code = fencecodes.right
-- local mathclasses = mathematics.classes
-- local fenceclasses = {
--- [left_fence_code] = mathclasses.open,
--- [middle_fence_code] = mathclasses.middle,
--- [right_fence_code] = mathclasses.close,
+-- [leftfence_code] = mathclasses.open,
+-- [middlefence_code] = mathclasses.middle,
+-- [rightfence_code] = mathclasses.close,
-- }
-- this initial stuff is tricky as we can have removed and new nodes with the same address
@@ -211,6 +218,7 @@ local right_fence_code = fencecodes.right
-- local sf = setfield local st = setmetatableindex("number") setfield = function(n,f,v) st[f] = st[f] + 1 sf(n,f,v) end mathematics.SETFIELD = st
local function process(start,what,n,parent)
+
if n then
n = n + 1
else
@@ -224,9 +232,9 @@ local function process(start,what,n,parent)
while start do
local id = getid(start)
if trace_processing then
- if id == math_noad then
+ if id == noad_code then
report_processing("%w%S, class %a",n*2,nutstring(start),noadcodes[getsubtype(start)])
- elseif id == math_char then
+ elseif id == mathchar_code then
local char = getchar(start)
local font = getfont(start)
local fam = getfam(start)
@@ -256,16 +264,16 @@ local function process(start,what,n,parent)
-- report_processing("stop processing")
end
end
- elseif id == math_noad then
+ elseif id == noad_code then
-- single characters are like this
local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list
noad = getsup (start) if noad then process(noad,what,n,start) end -- list
noad = getsub (start) if noad then process(noad,what,n,start) end -- list
- elseif id == math_char or id == math_textchar or id == math_delim then
+ elseif id == mathchar_code or id == mathtextchar_code or id == delim_code then
break
- elseif id == math_subbox or id == math_submlist then
+ elseif id == subbox_code or id == submlist_code then
local noad = getlist(start) if noad then process(noad,what,n,start) end -- list (not getlist !)
- elseif id == math_fraction then
+ elseif id == fraction_code then
local noad = getfield(start,"num") if noad then process(noad,what,n,start) end -- list
noad = getfield(start,"denom") if noad then process(noad,what,n,start) end -- list
noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter
@@ -275,21 +283,21 @@ local function process(start,what,n,parent)
noad = getfield(start,"text") if noad then process(noad,what,n,start) end -- list
noad = getfield(start,"script") if noad then process(noad,what,n,start) end -- list
noad = getfield(start,"scriptscript") if noad then process(noad,what,n,start) end -- list
- elseif id == math_fence then
+ elseif id == fence_code then
local noad = getfield(start,"delim") if noad then process(noad,what,n,start) end -- delimiter
- elseif id == math_radical then
+ elseif id == radical_code then
local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list
noad = getsup (start) if noad then process(noad,what,n,start) end -- list
noad = getsub (start) if noad then process(noad,what,n,start) end -- list
noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter
noad = getfield(start,"degree") if noad then process(noad,what,n,start) end -- list
- elseif id == math_accent then
+ elseif id == accent_code then
local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list
noad = getsup (start) if noad then process(noad,what,n,start) end -- list
noad = getsub (start) if noad then process(noad,what,n,start) end -- list
noad = getfield(start,"accent") if noad then process(noad,what,n,start) end -- list
noad = getfield(start,"bot_accent") if noad then process(noad,what,n,start) end -- list
- -- elseif id == math_style then
+ -- elseif id == style_code then
-- -- has a next
-- else
-- -- glue, penalty, etc
@@ -297,20 +305,20 @@ local function process(start,what,n,parent)
start = getnext(start)
end
if not parent then
- return initial, true -- only first level -- for now
+ return initial -- only first level -- for now
end
end
local function processnested(current,what,n)
local noad = nil
local id = getid(current)
- if id == math_noad then
+ if id == noad_code then
noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list
noad = getsup (current) if noad then process(noad,what,n,current) end -- list
noad = getsub (current) if noad then process(noad,what,n,current) end -- list
- elseif id == math_subbox or id == math_submlist then
+ elseif id == subbox_code or id == submlist_code then
noad = getlist(current) if noad then process(noad,what,n,current) end -- list (not getlist !)
- elseif id == math_fraction then
+ elseif id == fraction_code then
noad = getfield(current,"num") if noad then process(noad,what,n,current) end -- list
noad = getfield(current,"denom") if noad then process(noad,what,n,current) end -- list
noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter
@@ -320,15 +328,15 @@ local function processnested(current,what,n)
noad = getfield(current,"text") if noad then process(noad,what,n,current) end -- list
noad = getfield(current,"script") if noad then process(noad,what,n,current) end -- list
noad = getfield(current,"scriptscript") if noad then process(noad,what,n,current) end -- list
- elseif id == math_fence then
+ elseif id == fence_code then
noad = getfield(current,"delim") if noad then process(noad,what,n,current) end -- delimiter
- elseif id == math_radical then
+ elseif id == radical_code then
noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list
noad = getsup (current) if noad then process(noad,what,n,current) end -- list
noad = getsub (current) if noad then process(noad,what,n,current) end -- list
noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter
noad = getfield(current,"degree") if noad then process(noad,what,n,current) end -- list
- elseif id == math_accent then
+ elseif id == accent_code then
noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list
noad = getsup (current) if noad then process(noad,what,n,current) end -- list
noad = getsub (current) if noad then process(noad,what,n,current) end -- list
@@ -340,13 +348,13 @@ end
local function processstep(current,process,n,id)
local noad = nil
local id = id or getid(current)
- if id == math_noad then
+ if id == noad_code then
noad = getnucleus(current) if noad then process(noad,n,current) end -- list
noad = getsup (current) if noad then process(noad,n,current) end -- list
noad = getsub (current) if noad then process(noad,n,current) end -- list
- elseif id == math_subbox or id == math_submlist then
+ elseif id == subbox_code or id == submlist_code then
noad = getlist(current) if noad then process(noad,n,current) end -- list (not getlist !)
- elseif id == math_fraction then
+ elseif id == fraction_code then
noad = getfield(current,"num") if noad then process(noad,n,current) end -- list
noad = getfield(current,"denom") if noad then process(noad,n,current) end -- list
noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter
@@ -356,15 +364,15 @@ local function processstep(current,process,n,id)
noad = getfield(current,"text") if noad then process(noad,n,current) end -- list
noad = getfield(current,"script") if noad then process(noad,n,current) end -- list
noad = getfield(current,"scriptscript") if noad then process(noad,n,current) end -- list
- elseif id == math_fence then
+ elseif id == fence_code then
noad = getfield(current,"delim") if noad then process(noad,n,current) end -- delimiter
- elseif id == math_radical then
+ elseif id == radical_code then
noad = getnucleus(current) if noad then process(noad,n,current) end -- list
noad = getsup (current) if noad then process(noad,n,current) end -- list
noad = getsub (current) if noad then process(noad,n,current) end -- list
noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter
noad = getfield(current,"degree") if noad then process(noad,n,current) end -- list
- elseif id == math_accent then
+ elseif id == accent_code then
noad = getnucleus(current) if noad then process(noad,n,current) end -- list
noad = getsup (current) if noad then process(noad,n,current) end -- list
noad = getsub (current) if noad then process(noad,n,current) end -- list
@@ -374,15 +382,14 @@ local function processstep(current,process,n,id)
end
local function processnoads(head,actions,banner)
- local h, d
if trace_processing then
report_processing("start %a",banner)
- h, d = process(tonut(head),actions)
+ head = process(head,actions)
report_processing("stop %a",banner)
else
- h, d = process(tonut(head),actions)
+ head = process(head,actions)
end
- return h and tonode(h) or head, d == nil and true or d
+ return head
end
noads.process = processnoads
@@ -456,7 +463,35 @@ do
"pseudobold",
}
- families[math_char] = function(pointer)
+ families[fraction_code] = function(pointer,what,n,parent)
+ local a = getattr(pointer,a_mathfamily)
+ if a and a >= 0 then
+ if a > 0 then
+ setattr(pointer,a_mathfamily,0)
+ if a > 5 then
+ a = a - 3
+ end
+ end
+ setfam(pointer,a)
+ end
+ processnested(pointer,families,n+1)
+ end
+
+ families[noad_code] = function(pointer,what,n,parent)
+ local a = getattr(pointer,a_mathfamily)
+ if a and a >= 0 then
+ if a > 0 then
+ setattr(pointer,a_mathfamily,0)
+ if a > 5 then
+ a = a - 3
+ end
+ end
+ setfam(pointer,a)
+ end
+ processnested(pointer,families,n+1)
+ end
+
+ families[mathchar_code] = function(pointer)
if getfam(pointer) == 0 then
local a = getattr(pointer,a_mathfamily)
if a and a > 0 then
@@ -501,8 +536,7 @@ do
end
end
end
-
- families[math_delim] = function(pointer)
+ families[delim_code] = function(pointer)
if getfield(pointer,"small_fam") == 0 then
local a = getattr(pointer,a_mathfamily)
if a and a > 0 then
@@ -534,7 +568,7 @@ do
-- will become:
- -- families[math_delim] = function(pointer)
+ -- families[delim_code] = function(pointer)
-- if getfam(pointer) == 0 then
-- local a = getattr(pointer,a_mathfamily)
-- if a and a > 0 then
@@ -556,11 +590,11 @@ do
-- end
-- end
- families[math_textchar] = families[math_char]
+ families[mathtextchar_code] = families[mathchar_code]
function handlers.families(head,style,penalties)
processnoads(head,families,"families")
- return true
+ return true -- not needed
end
end
@@ -604,7 +638,7 @@ do
end
end
- relocate[math_char] = function(pointer)
+ relocate[mathchar_code] = function(pointer)
local g = getattr(pointer,a_mathgreek) or 0
local a = getattr(pointer,a_mathalphabet) or 0
local char = getchar(pointer)
@@ -671,13 +705,13 @@ do
end
end
- relocate[math_textchar] = function(pointer)
+ relocate[mathtextchar_code] = function(pointer)
if trace_analyzing then
setnodecolor(pointer,"font:init")
end
end
- relocate[math_delim] = function(pointer)
+ relocate[delim_code] = function(pointer)
if trace_analyzing then
setnodecolor(pointer,"font:fina")
end
@@ -685,7 +719,7 @@ do
function handlers.relocate(head,style,penalties)
processnoads(head,relocate,"relocate")
- return true
+ return true -- not needed
end
end
@@ -698,7 +732,7 @@ do
local rendersets = mathematics.renderings.numbers or { } -- store
- render[math_char] = function(pointer)
+ render[mathchar_code] = function(pointer)
local attr = getattr(pointer,a_mathrendering)
if attr and attr > 0 then
local char = getchar(pointer)
@@ -719,7 +753,7 @@ do
function handlers.render(head,style,penalties)
processnoads(head,render,"render")
- return true
+ return true -- not needed
end
end
@@ -739,51 +773,46 @@ do
local a_mathsize = privateattribute("mathsize") -- this might move into other fence code
local resize = { }
- resize[math_fence] = function(pointer)
+ resize[fence_code] = function(pointer)
local subtype = getsubtype(pointer)
- if subtype == left_fence_code or subtype == right_fence_code then
+ if subtype == leftfence_code or subtype == rightfence_code then
local a = getattr(pointer,a_mathsize)
if a and a > 0 then
- local method, size = div(a,100), a % 100
+ local method = div(a,100)
+ local size = a % 100
setattr(pointer,a_mathsize,0)
local delimiter = getfield(pointer,"delim")
- local chr = getfield(delimiter,"small_char")
+ local chr = getchar(delimiter)
if chr > 0 then
- local fam = getfield(delimiter,"small_fam")
+ local fam = getfam(delimiter)
local id = font_of_family(fam)
if id > 0 then
- setfield(delimiter,"small_char",mathematics.big(fontdata[id],chr,size,method))
+ local data = fontdata[id]
+ local char = mathematics.big(data,chr,size,method)
+ local ht = getheight(pointer)
+ local dp = getdepth(pointer)
+ if ht == 1 or dp == 1 then -- 1 scaled point is a signal
+ local chardata = data.characters[char]
+ if ht == 1 then
+ setheight(pointer,chardata.height)
+ end
+ if dp == 1 then
+ setdepth(pointer,chardata.depth)
+ end
+ end
+ if trace_fences then
+ report_fences("replacing %C by %C using method %a and size %a",chr,char,method,size)
+ end
+ setchar(delimiter,char)
end
end
end
end
end
- -- will become:
-
- -- resize[math_fence] = function(pointer)
- -- local subtype = getsubtype(pointer)
- -- if subtype == left_fence_code or subtype == right_fence_code then
- -- local a = getattr(pointer,a_mathsize)
- -- if a and a > 0 then
- -- local method, size = div(a,100), a % 100
- -- setattr(pointer,a_mathsize,0)
- -- local delimiter = getfield(pointer,"delim")
- -- local chr = getchar(delimiter)
- -- if chr > 0 then
- -- local fam = getfam(delimiter)
- -- local id = font_of_family(fam)
- -- if id > 0 then
- -- setchar(delimiter,mathematics.big(fontdata[id],chr,size,method))
- -- end
- -- end
- -- end
- -- end
- -- end
-
function handlers.resize(head,style,penalties)
processnoads(head,resize,"resize")
- return true
+ return true -- not needed
end
end
@@ -797,8 +826,8 @@ do
local dummyfencechar = 0x2E
local function makefence(what,char)
- local d = new_delimiter()
- local f = new_fence()
+ local d = new_delimiter() -- todo: attr
+ local f = new_fence() -- todo: attr
if char then
local sym = getnucleus(char)
local chr = getchar(sym)
@@ -821,8 +850,8 @@ do
-- will become
-- local function makefence(what,char)
- -- local d = new_delimiter()
- -- local f = new_fence()
+ -- local d = new_delimiter() -- todo: attr
+ -- local f = new_fence() -- todo: attr
-- if char then
-- local sym = getnucleus(char)
-- local chr = getchar(sym)
@@ -843,7 +872,7 @@ do
local function makelist(noad,f_o,o_next,c_prev,f_c,middle)
local list = new_submlist()
setlist(list,f_o)
- setsubtype(noad,noad_inner)
+ setsubtype(noad,innernoad_code)
setnucleus(noad,list)
setlink(f_o,o_next)
setlink(c_prev,f_c)
@@ -854,7 +883,7 @@ do
local m = middle[current]
if m then
local next = getnext(current)
- local fence = makefence(middle_fence_code,current)
+ local fence = makefence(middlefence_code,current)
setnucleus(current)
flush_node(current)
middle[current] = nil
@@ -876,8 +905,8 @@ do
if o_next == close then
return close
else
- local f_o = makefence(left_fence_code,open)
- local f_c = makefence(right_fence_code,close)
+ local f_o = makefence(leftfence_code,open)
+ local f_c = makefence(rightfence_code,close)
makelist(open,f_o,o_next,c_prev,f_c,middle)
setnucleus(close)
flush_node(close)
@@ -890,8 +919,8 @@ do
end
local function convert_open(open,last,middle)
- local f_o = makefence(left_fence_code,open)
- local f_c = makefence(right_fence_code)
+ local f_o = makefence(leftfence_code,open)
+ local f_c = makefence(rightfence_code)
local o_prev, o_next = getboth(open)
local l_prev, l_next = getboth(last)
makelist(open,f_o,o_next,last,f_c,middle)
@@ -903,8 +932,8 @@ do
end
local function convert_close(close,first,middle)
- local f_o = makefence(left_fence_code)
- local f_c = makefence(right_fence_code,close)
+ local f_o = makefence(leftfence_code)
+ local f_c = makefence(rightfence_code,close)
local c_prev = getprev(close)
makelist(close,f_o,first,c_prev,f_c,middle)
return close
@@ -922,7 +951,7 @@ do
local middle = nil -- todo: use properties
while current do
local id = getid(current)
- if id == math_noad then
+ if id == noad_code then
local a = getattr(current,a_autofence)
if a and a > 0 then
local stack = stacks[n]
@@ -1009,7 +1038,7 @@ do
function handlers.autofences(head,style,penalties)
if enabled then -- tex.modes.c_math_fences_auto
-- inspect(nodes.totree(head))
- processfences(tonut(head),1)
+ processfences(head,1)
-- inspect(nodes.totree(head))
end
end
@@ -1031,9 +1060,9 @@ do
local next = getnext(pointer)
local start_super, stop_super, start_sub, stop_sub
local mode = "unset"
- while next and getid(next) == math_noad do
+ while next and getid(next) == noad_code do
local nextnucleus = getnucleus(next)
- if nextnucleus and getid(nextnucleus) == math_char and not getsub(next) and not getsup(next) then
+ if nextnucleus and getid(nextnucleus) == mathchar_code and not getsub(next) and not getsup(next) then
local char = getchar(nextnucleus)
local s = superscripts[char]
if s then
@@ -1088,6 +1117,18 @@ do
setnext(stop_super)
end
if start_sub then
+
+-- if mode == "sub" then
+-- local sup = getsup(pointer)
+-- if sup and not getsub(pointer) then
+-- local nxt = getnext(pointer)
+-- local new = new_noad(pointer)
+-- setnucleus(new,new_submlist())
+-- setlink(pointer,new,nxt)
+-- pointer = new
+-- end
+-- end
+
if start_sub == stop_sub then
setsub(pointer,getnucleus(start_sub))
else
@@ -1103,18 +1144,59 @@ do
-- we could return stop
end
- unscript[math_char] = replace -- not noads as we need to recurse
+ unscript[mathchar_code] = replace -- not noads as we need to recurse
function handlers.unscript(head,style,penalties)
processnoads(head,unscript,"unscript")
- -- processnoads(head,checkers,"checkers")
- return true
+ return true -- not needed
end
end
do
+ local unstack = { } noads.processors.unstack = unstack
+ local enabled = false
+ local a_unstack = privateattribute("mathunstack")
+
+ unstack[noad_code] = function(pointer)
+ if getattr(pointer,a_unstack) then
+ local sup = getsup(pointer)
+ local sub = getsub(pointer)
+ if sup and sub then
+ -- if trace_unstacking then
+ -- report_unstacking() -- todo ... what to show ...
+ -- end
+ local nxt = getnext(pointer)
+ local new = new_noad(pointer)
+ setnucleus(new,new_submlist())
+ setsub(pointer)
+ setsub(new,sub)
+ setlink(pointer,new,nxt)
+ end
+ end
+ end
+
+ function handlers.unstack(head,style,penalties)
+ if enabled then
+ processnoads(head,unstack,"unstack")
+ return true -- not needed
+ end
+ end
+
+ implement {
+ name = "enablescriptunstacking",
+ onlyonce = true,
+ actions = function()
+ enableaction("math","noads.handlers.unstack")
+ enabled = true
+ end
+ }
+
+end
+
+do
+
local function collected(list)
if list and next(list) then
local n, t = 0, { }
@@ -1306,7 +1388,7 @@ do
arguments = { "integer", "string" }
}
- alternate[math_char] = function(pointer) -- slow
+ alternate[mathchar_code] = function(pointer) -- slow
local a = getattr(pointer,a_mathalternate)
if a and a > 0 then
setattr(pointer,a_mathalternate,0)
@@ -1347,7 +1429,7 @@ do
function handlers.alternates(head,style,penalties)
processnoads(head,alternate,"alternate")
- return true
+ return true -- not needed
end
end
@@ -1365,7 +1447,7 @@ end
-- in opentype the italic correction of a limop is added to the width and luatex does
-- some juggling that we want to avoid but we need to do something here (in fact, we could
--- better fix the width of the character
+-- better fix the width of the character)
do
@@ -1382,8 +1464,8 @@ do
local c_negative_d = "trace:dr"
local function insert_kern(current,kern)
- local sub = new_submlist()
- local noad = new_noad()
+ local sub = new_submlist() -- todo: attr
+ local noad = new_noad() -- todo: attr
setlist(sub,kern)
setnext(kern,noad)
setnucleus(noad,current)
@@ -1393,7 +1475,7 @@ do
registertracker("math.italics.visualize", function(v)
if v then
italic_kern = function(k)
- local n = new_kern(k)
+ local n = new_kern(k) -- todo: attr
set_visual(n,"italic")
return n
end
@@ -1454,7 +1536,7 @@ do
end
- italics[math_char] = function(pointer,what,n,parent)
+ italics[mathchar_code] = function(pointer,what,n,parent)
local method = getattr(pointer,a_mathitalics)
if method and method > 0 and method < 100 then
local char = getchar(pointer)
@@ -1485,7 +1567,7 @@ do
function handlers.italics(head,style,penalties)
processnoads(head,italics,"italics")
- return true
+ return true -- not needed
end
local enable = function()
@@ -1582,7 +1664,7 @@ do
-- no correction after prime because that moved to a superscript
- kernpairs[math_char] = function(pointer,what,n,parent)
+ kernpairs[mathchar_code] = function(pointer,what,n,parent)
if getattr(pointer,a_kernpairs) == 1 then
local font = getfont(pointer)
local list = hash[font]
@@ -1591,7 +1673,7 @@ do
local found = list[first]
if found then
local next = getnext(parent)
- if next and getid(next) == math_noad then
+ if next and getid(next) == noad_code then
pointer = getnucleus(next)
if pointer then
if getfont(pointer) == font then
@@ -1602,7 +1684,7 @@ do
if trace_kernpairs then
report_kernpairs("adding %p kerning between %C and %C",kern,first,second)
end
- setlink(parent,new_kern(kern),getnext(parent))
+ setlink(parent,new_kern(kern),getnext(parent)) -- todo: attr
end
end
end
@@ -1614,7 +1696,7 @@ do
function handlers.kernpairs(head,style,penalties)
processnoads(head,kernpairs,"kernpairs")
- return true
+ return true -- not needed
end
end
@@ -1629,20 +1711,20 @@ do
local collapse = { }
local mathlists = characters.mathlists
local validpair = {
- [noad_ord] = true,
- [noad_rel] = true,
- [noad_bin] = true, -- new
- [noad_open] = true, -- new
- [noad_close] = true, -- new
- [noad_punct] = true, -- new
- [noad_opdisplaylimits] = true,
- [noad_oplimits] = true,
- [noad_opnolimits] = true,
+ [ordnoad_code] = true,
+ [relnode_code] = true,
+ [binnoad_code] = true, -- new
+ [opennoad_code] = true, -- new
+ [closenoad_code] = true, -- new
+ [punctnoad_code] = true, -- new
+ [opdisplaylimitsnoad_code] = true,
+ [oplimitsnoad_code] = true,
+ [opnolimitsnoad_code] = true,
}
local reported = setmetatableindex("table")
- collapse[math_char] = function(pointer,what,n,parent)
+ collapse[mathchar_code] = function(pointer,what,n,parent)
if parent and mathlists[getchar(pointer)] then
local found, last, lucleus, lsup, lsub, category
@@ -1727,7 +1809,7 @@ do
function noads.handlers.collapse(head,style,penalties)
processnoads(head,collapse,"collapse")
- return true
+ return true -- not needed
end
local enable = function()
@@ -1784,7 +1866,7 @@ do
-- local function movesubscript(parent,current_nucleus,oldchar,newchar)
-- local prev = getprev(parent)
- -- if prev and getid(prev) == math_noad then
+ -- if prev and getid(prev) == noad_code then
-- local psup = getsup(prev)
-- local psub = getsub(prev)
-- if not psup and not psub then
@@ -1827,7 +1909,7 @@ do
setnucleus(parent,dummy)
end
- fixscripts[math_char] = function(pointer,what,n,parent,nested) -- todo: switch to turn in on and off
+ fixscripts[mathchar_code] = function(pointer,what,n,parent,nested) -- todo: switch to turn in on and off
if parent then
local oldchar = getchar(pointer)
local newchar = movesub[oldchar]
@@ -1846,7 +1928,7 @@ do
-- print("[char] --- sup")
else
local prev = getprev(parent)
- if prev and getid(prev) == math_noad then
+ if prev and getid(prev) == noad_code then
local psub = getsub(prev)
local psup = getsup(prev)
if psub then
@@ -1875,7 +1957,7 @@ do
function noads.handlers.fixscripts(head,style,penalties)
processnoads(head,fixscripts,"fixscripts")
- return true
+ return true -- not needed
end
end
@@ -1901,14 +1983,14 @@ do
[0x2ACB] = 0xFE00, [0x2ACC] = 0xFE00,
}
- variants[math_char] = function(pointer,what,n,parent) -- also set export value
+ variants[mathchar_code] = function(pointer,what,n,parent) -- also set export value
local char = getchar(pointer)
local selector = validvariants[char]
if selector then
local next = getnext(parent)
- if next and getid(next) == math_noad then
+ if next and getid(next) == noad_code then
local nucleus = getnucleus(next)
- if nucleus and getid(nucleus) == math_char and getchar(nucleus) == selector then
+ if nucleus and getid(nucleus) == mathchar_code and getchar(nucleus) == selector then
local variant
local tfmdata = fontdata[getfont(pointer)]
local mathvariants = tfmdata.resources.variants -- and variantdata
@@ -1939,7 +2021,7 @@ do
function handlers.variants(head,style,penalties)
processnoads(head,variants,"unicode variant")
- return true
+ return true -- not needed
end
end
@@ -1950,25 +2032,25 @@ do
local classes = { }
local colors = {
- [noad_rel] = "trace:dr",
- [noad_ord] = "trace:db",
- [noad_bin] = "trace:dg",
- [noad_open] = "trace:dm",
- [noad_close] = "trace:dm",
- [noad_punct] = "trace:dc",
- -- [noad_opdisplaylimits] = "",
- -- [noad_oplimits] = "",
- -- [noad_opnolimits] = "",
- -- [noad_inner = "",
- -- [noad_under = "",
- -- [noad_over = "",
- -- [noad_vcenter = "",
+ [relnode_code] = "trace:dr",
+ [ordnoad_code] = "trace:db",
+ [binnoad_code] = "trace:dg",
+ [opennoad_code] = "trace:dm",
+ [closenoad_code] = "trace:dm",
+ [punctnoad_code] = "trace:dc",
+ -- [opdisplaylimitsnoad_code] = "",
+ -- [oplimitsnoad_code] = "",
+ -- [opnolimitsnoad_code] = "",
+ -- [innernoad_code = "",
+ -- [undernoad_code] = "",
+ -- [overnoad_code] = "",
+ -- [vcenternoad_code] = "",
}
local setcolor = colortracers.set
local resetcolor = colortracers.reset
- classes[math_char] = function(pointer,what,n,parent)
+ classes[mathchar_code] = function(pointer,what,n,parent)
local color = colors[getsubtype(parent)]
if color then
setcolor(pointer,color)
@@ -1979,7 +2061,7 @@ do
function handlers.classes(head,style,penalties)
processnoads(head,classes,"classes")
- return true
+ return true -- not needed
end
registertracker("math.classes",function(v)
@@ -2006,11 +2088,11 @@ do
local a_mathdomain = privateattribute("mathdomain")
mathematics.domains = categories
local permitted = {
- ordinary = noad_ord,
- binary = noad_bin,
- relation = noad_rel,
- punctuation = noad_punct,
- inner = noad_inner,
+ ordinary = ordnoad_code,
+ binary = binnoad_code,
+ relation = relnode_code,
+ punctuation = punctnoad_code,
+ inner = innernoad_code,
}
function mathematics.registerdomain(data)
@@ -2113,7 +2195,7 @@ do
return hash
end
- domains[math_char] = function(pointer,what,n,parent)
+ domains[mathchar_code] = function(pointer,what,n,parent)
local attr = getattr(pointer,a_mathdomain)
if attr then
local domain = numbers[attr]
@@ -2140,7 +2222,7 @@ do
function handlers.domains(head,style,penalties)
processnoads(head,domains,"domains")
- return true
+ return true -- not needed
end
end
@@ -2148,7 +2230,7 @@ end
-- just for me
function handlers.showtree(head,style,penalties)
- inspect(nodes.totree(head))
+ inspect(nodes.totree(tonut(head)))
end
registertracker("math.showtree",function(v)
@@ -2163,7 +2245,7 @@ do
local visual = false
function handlers.makeup(head)
- applyvisuals(tonut(head),visual)
+ applyvisuals(head,visual)
end
registertracker("math.makeup",function(v)
@@ -2184,9 +2266,15 @@ do
-- end)
function builders.kernel.mlist_to_hlist(head,style,penalties)
- return mlist_to_hlist(head,style,force_penalties or penalties), true
+ return mlist_to_hlist(head,style,force_penalties or penalties)
end
+ -- function builders.kernel.mlist_to_hlist(head,style,penalties)
+ -- local h = mlist_to_hlist(head,style,force_penalties or penalties)
+ -- inspect(nodes.totree(h,true,true,true))
+ -- return h
+ -- end
+
implement {
name = "setmathpenalties",
arguments = "integer",
@@ -2197,41 +2285,15 @@ do
end
--- function builders.kernel.mlist_to_hlist(head,style,penalties)
--- print("!!!!!!! BEFORE",penalties)
--- for n in node.traverse(head) do print(n) end
--- print("!!!!!!!")
--- head = mlist_to_hlist(head,style,penalties)
--- print("!!!!!!! AFTER")
--- for n in node.traverse(head) do print(n) end
--- print("!!!!!!!")
--- return head, true
--- end
-
-tasks.new {
- name = "math",
- arguments = 2,
- processor = utilities.sequencers.nodeprocessor,
- sequence = {
- "before",
- "normalizers",
- "builders",
- "after",
- },
-}
-
-tasks.freezegroup("math", "normalizers") -- experimental
-tasks.freezegroup("math", "builders") -- experimental
-
local actions = tasks.actions("math") -- head, style, penalties
local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
function processors.mlist_to_hlist(head,style,penalties)
starttiming(noads)
- local head, done = actions(head,style,penalties)
+ head = actions(head,style,penalties)
stoptiming(noads)
- return head, done
+ return head
end
callbacks.register('mlist_to_hlist',processors.mlist_to_hlist,"preprocessing math list")
diff --git a/tex/context/base/mkiv/math-pln.mkiv b/tex/context/base/mkiv/math-pln.mkiv
index d0e7e377d..1003444b8 100644
--- a/tex/context/base/mkiv/math-pln.mkiv
+++ b/tex/context/base/mkiv/math-pln.mkiv
@@ -171,7 +171,7 @@
\crcr
\noalign\bgroup
\kern\scratchdimentwo
- \global\let\cr\endline
+ \glet\cr\endline
\egroup
}%
\ialign{%
diff --git a/tex/context/base/mkiv/math-spa.lua b/tex/context/base/mkiv/math-spa.lua
index 92ee662b9..33d9501d8 100644
--- a/tex/context/base/mkiv/math-spa.lua
+++ b/tex/context/base/mkiv/math-spa.lua
@@ -8,24 +8,23 @@ if not modules then modules = { } end modules ['math-spa'] = {
-- for the moment (when testing) we use a penalty 1
-local penalty_code = nodes.nodecodes.penalty
-local glue_code = nodes.nodecodes.glue
+local penalty_code = nodes.nodecodes.penalty
+local glue_code = nodes.nodecodes.glue
-local nuts = nodes.nuts
-local tonut = nodes.tonut
-local tonode = nodes.tonode
-local getid = nuts.getid
-local getnext = nuts.getnext
-local getwidth = nuts.getwidth
-local setglue = nuts.setglue
-local getpenalty = nuts.getpenalty
-local setpenalty = nuts.setpenalty
+local nuts = nodes.nuts
+local tonut = nodes.tonut
+local tonode = nodes.tonode
-local traverse_id = nuts.traverse_id
-local get_dimensions = nuts.dimensions
+local getid = nuts.getid
+local getnext = nuts.getnext
+local getwidth = nuts.getwidth
+local setglue = nuts.setglue
+local getpenalty = nuts.getpenalty
+local setpenalty = nuts.setpenalty
+local getdimensions = nuts.dimensions
+local nextglue = nuts.traversers.glue
-
-local texsetdimen = tex.setdimen
+local texsetdimen = tex.setdimen
local v_none = interfaces.variables.none
local v_auto = interfaces.variables.auto
@@ -33,9 +32,8 @@ local v_auto = interfaces.variables.auto
local method = v_none
local distance = 0
-function noads.handlers.align(l)
+function noads.handlers.align(h)
if method ~= v_none then
- local h = tonut(l)
if method == v_auto then
local s = h
while s do
@@ -47,7 +45,7 @@ function noads.handlers.align(l)
s = n
n = getnext(s)
end
- local w = get_dimensions(h,n) + distance
+ local w = getdimensions(h,n) + distance
texsetdimen("global","d_strc_math_indent",w)
break
end
@@ -56,13 +54,12 @@ function noads.handlers.align(l)
else
texsetdimen("global","d_strc_math_indent",distance)
end
- for n in traverse_id(glue_code,h) do
+ for n in nextglue, h do
setglue(n,getwidth(n),0,0)
end
else
-- texsetdimen("global","d_strc_math_indent",0)
end
- return l, true
end
interfaces.implement {
diff --git a/tex/context/base/mkiv/math-stc.mkvi b/tex/context/base/mkiv/math-stc.mkvi
index c9d469d61..92325d0af 100644
--- a/tex/context/base/mkiv/math-stc.mkvi
+++ b/tex/context/base/mkiv/math-stc.mkvi
@@ -413,13 +413,13 @@
\fi
%
\ifdim\wd\scratchboxone<\scratchwidth
- \setbox\scratchboxone\hbox to \scratchwidth{\hss\unhbox\scratchboxone\hss}% unhboxing makes leaders work
+ \setbox\scratchboxone\hpack to \scratchwidth{\hss\unhbox\scratchboxone\hss}% unhboxing makes leaders work
\fi
\ifdim\wd\scratchboxtwo<\scratchwidth
- \setbox\scratchboxtwo\hbox to \scratchwidth{\hss\unhbox\scratchboxtwo\hss}%
+ \setbox\scratchboxtwo\hpack to \scratchwidth{\hss\unhbox\scratchboxtwo\hss}%
\fi
\ifdim\wd\scratchboxthree<\scratchwidth
- \setbox\scratchboxthree\hbox to \scratchwidth{\hss\unhbox\scratchboxthree\hss}%
+ \setbox\scratchboxthree\hpack to \scratchwidth{\hss\unhbox\scratchboxthree\hss}%
\fi
%
\ifcsname\??mathstackerslocation\p_location\endcsname
@@ -448,7 +448,7 @@
\fi
%
\ifzeropt\scratchdistance\else
- \setbox\scratchboxthree\hbox{\lower\scratchdistance\box\scratchboxthree}%
+ \setbox\scratchboxthree\hpack{\lower\scratchdistance\box\scratchboxthree}%
\fi
%
\math_stackers_normalize_three
@@ -603,7 +603,7 @@
\advance\scratchwidth2\scratchhoffset
%
\setbox\scratchboxtwo\csname\??mathstackersalternative\p_alternative\endcsname
- \setbox\scratchboxthree\hbox to \scratchwidth{\hss\box\scratchboxthree\hss}%
+ \setbox\scratchboxthree\hpack to \scratchwidth{\hss\box\scratchboxthree\hss}%
%
\scratchunicode#codeextra\relax
\ifcase\scratchunicode\else
@@ -803,10 +803,10 @@
\advance\scratchwidth2\scratchhoffset
%
\ifdim\wd\scratchboxone<\scratchwidth
- \setbox\scratchboxone\hbox to \scratchwidth{\hss\unhbox\scratchboxone\hss}%
+ \setbox\scratchboxone\hpack to \scratchwidth{\hss\unhbox\scratchboxone\hss}%
\fi
\ifdim\wd\scratchboxthree<\scratchwidth
- \setbox\scratchboxthree\hbox to \scratchwidth{\hss\unhbox\scratchboxthree\hss}%
+ \setbox\scratchboxthree\hpack to \scratchwidth{\hss\unhbox\scratchboxthree\hss}%
\fi
%
\math_stackers_normalize_three
diff --git a/tex/context/base/mkiv/math-tag.lua b/tex/context/base/mkiv/math-tag.lua
index d1ed90d38..03f9e70bb 100644
--- a/tex/context/base/mkiv/math-tag.lua
+++ b/tex/context/base/mkiv/math-tag.lua
@@ -14,90 +14,92 @@ if not modules then modules = { } end modules ['math-tag'] = {
local find, match = string.find, string.match
local insert, remove, concat = table.insert, table.remove, table.concat
-local attributes = attributes
-local nodes = nodes
-
-local nuts = nodes.nuts
-local tonut = nuts.tonut
-
-local getnext = nuts.getnext
-local getid = nuts.getid
-local getchar = nuts.getchar
-local getfont = nuts.getfont
-local getlist = nuts.getlist
-local getfield = nuts.getfield
-local getdisc = nuts.getdisc
-local getsubtype = nuts.getsubtype
-local getattr = nuts.getattr
-local setattr = nuts.setattr
-local getcomponents = nuts.getcomponents
-local getwidth = nuts.getwidth
-
-local getnucleus = nuts.getnucleus
-local getsub = nuts.getsub
-local getsup = nuts.getsup
-
-local set_attributes = nuts.setattributes
-local traverse_nodes = nuts.traverse
-
-local nodecodes = nodes.nodecodes
-
-local math_noad_code = nodecodes.noad -- attr nucleus sub sup
-local math_accent_code = nodecodes.accent -- attr nucleus sub sup accent
-local math_radical_code = nodecodes.radical -- attr nucleus sub sup left degree
-local math_fraction_code = nodecodes.fraction -- attr nucleus sub sup left right
-local math_box_code = nodecodes.subbox -- attr list
-local math_sub_code = nodecodes.submlist -- attr list
-local math_char_code = nodecodes.mathchar -- attr fam char
-local math_textchar_code = nodecodes.mathtextchar -- attr fam char
-local math_delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char
-local math_style_code = nodecodes.style -- attr style
-local math_choice_code = nodecodes.choice -- attr display text script scriptscript
-local math_fence_code = nodecodes.fence -- attr subtype
-
-local accentcodes = nodes.accentcodes
-
-local math_fixed_top = accentcodes.fixedtop
-local math_fixed_bottom = accentcodes.fixedbottom
-local math_fixed_both = accentcodes.fixedboth
-
-local kerncodes = nodes.kerncodes
-
-local fontkern_code = kerncodes.fontkern
-local italickern_code = kerncodes.italickern
-
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local glyph_code = nodecodes.glyph
-local disc_code = nodecodes.disc
-local glue_code = nodecodes.glue
-local kern_code = nodecodes.kern
-local math_code = nodecodes.math
-
-local processnoads = noads.process
-
-local a_tagged = attributes.private('tagged')
-local a_mathcategory = attributes.private('mathcategory')
-local a_mathmode = attributes.private('mathmode')
-
-local tags = structures.tags
-
-local start_tagged = tags.start
-local restart_tagged = tags.restart
-local stop_tagged = tags.stop
-local taglist = tags.taglist
-
-local chardata = characters.data
-
-local getmathcodes = tex.getmathcodes
-local mathcodes = mathematics.codes
-local ordinary_code = mathcodes.ordinary
-local variable_code = mathcodes.variable
-
-local fromunicode16 = fonts.mappings.fromunicode16
-local fontcharacters = fonts.hashes.characters
-
-local report_tags = logs.reporter("structure","tags")
+local attributes = attributes
+local nodes = nodes
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+
+local getnext = nuts.getnext
+local getid = nuts.getid
+local getchar = nuts.getchar
+local getfont = nuts.getfont
+local getlist = nuts.getlist
+local getfield = nuts.getfield
+local getdisc = nuts.getdisc
+local getsubtype = nuts.getsubtype
+local getattr = nuts.getattr
+local getattrlist = nuts.getattrlist
+local setattr = nuts.setattr
+local getcomponents = nuts.getcomponents -- not really needed
+local getwidth = nuts.getwidth
+
+local getnucleus = nuts.getnucleus
+local getsub = nuts.getsub
+local getsup = nuts.getsup
+
+local set_attributes = nuts.setattributes
+
+local nextnode = nuts.traversers.node
+
+local nodecodes = nodes.nodecodes
+
+local noad_code = nodecodes.noad -- attr nucleus sub sup
+local accent_code = nodecodes.accent -- attr nucleus sub sup accent
+local radical_code = nodecodes.radical -- attr nucleus sub sup left degree
+local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right
+local subbox_code = nodecodes.subbox -- attr list
+local submlist_code = nodecodes.submlist -- attr list
+local mathchar_code = nodecodes.mathchar -- attr fam char
+local mathtextchar_code = nodecodes.mathtextchar -- attr fam char
+local delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char
+local style_code = nodecodes.style -- attr style
+local choice_code = nodecodes.choice -- attr display text script scriptscript
+local fence_code = nodecodes.fence -- attr subtype
+
+local accentcodes = nodes.accentcodes
+
+local fixedtopaccent_code = accentcodes.fixedtop
+local fixedbottomaccent_code = accentcodes.fixedbottom
+local fixedbothaccent_code = accentcodes.fixedboth
+
+local kerncodes = nodes.kerncodes
+
+local fontkern_code = kerncodes.fontkern
+local italickern_code = kerncodes.italickern
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+local math_code = nodecodes.math
+
+local processnoads = noads.process
+
+local a_tagged = attributes.private('tagged')
+local a_mathcategory = attributes.private('mathcategory')
+local a_mathmode = attributes.private('mathmode')
+
+local tags = structures.tags
+
+local start_tagged = tags.start
+local restart_tagged = tags.restart
+local stop_tagged = tags.stop
+local taglist = tags.taglist
+
+local chardata = characters.data
+
+local getmathcodes = tex.getmathcodes
+local mathcodes = mathematics.codes
+local ordinary_mathcode = mathcodes.ordinary
+local variable_mathcode = mathcodes.variable
+
+local fromunicode16 = fonts.mappings.fromunicode16
+local fontcharacters = fonts.hashes.characters
+
+local report_tags = logs.reporter("structure","tags")
local process
@@ -154,12 +156,19 @@ local fencesstack = { }
-- glyph nodes and such can happen in under and over stuff
+-- local function getunicode(n) -- instead of getchar
+-- local char = getchar(n)
+-- -- local font = font_of_family(getfield(n,"fam")) -- font_of_family
+-- local font = getfont(n)
+-- local data = fontcharacters[font][char]
+-- return data.unicode or char
+-- end
+
local function getunicode(n) -- instead of getchar
- local char = getchar(n)
- -- local font = font_of_family(getfield(n,"fam")) -- font_of_family
- local font = getfont(n)
+ -- local char, font = isglyph(n) -- no, we have a mathchar
+ local char, font = getchar(n), getfont(n)
local data = fontcharacters[font][char]
- return data.unicode or char
+ return data.unicode or char -- can be a table but unlikely for math characters
end
-------------------
@@ -167,7 +176,7 @@ end
local content = { }
local found = false
-content[math_char_code] = function() found = true end
+content[mathchar_code] = function() found = true end
local function hascontent(head)
found = false
@@ -177,18 +186,25 @@ end
--------------------
-local function showtag(n,id)
- local attr = getattr(n,a_tagged)
- report_tags("%s = %s",nodecodes[id or getid(n)],attr and taglist[attr].tagname or "?")
-end
+-- todo: use properties
+
+-- local function showtag(n,id,old)
+-- local attr = getattr(n,a_tagged)
+-- local curr = tags.current()
+-- report_tags("%s, node %s, attr %s:%s (%s), top %s (%s)",
+-- old and "before" or "after ",
+-- nodecodes[id],
+-- getattrlist(n),
+-- attr or "?",attr and taglist[attr].tagname or "?",
+-- curr or "?",curr and taglist[curr].tagname or "?"
+-- )
+-- end
process = function(start) -- we cannot use the processor as we have no finalizers (yet)
local mtexttag = nil
while start do
local id = getid(start)
-
--- showtag(start,id)
-
+ -- showtag(start,id,true)
if id == glyph_code or id == disc_code then
if not mtexttag then
mtexttag = start_tagged("mtext")
@@ -201,11 +217,11 @@ process = function(start) -- we cannot use the processor as we have no finalizer
stop_tagged()
mtexttag = nil
end
- if id == math_char_code then
+ if id == mathchar_code then
local char = getchar(start)
local code = getmathcodes(char)
local tag
- if code == ordinary_code or code == variable_code then
+ if code == ordinary_mathcode or code == variable_mathcode then
local ch = chardata[char]
local mc = ch and ch.mathclass
if mc == "number" then
@@ -225,8 +241,9 @@ process = function(start) -- we cannot use the processor as we have no finalizer
setattr(start,a_tagged,start_tagged(tag)) -- todo: a_mathcategory
end
stop_tagged()
+ -- showtag(start,id,false)
break -- okay?
- elseif id == math_textchar_code then -- or id == glyph_code
+ elseif id == mathtextchar_code then -- or id == glyph_code
-- check for code
local a = getattr(start,a_mathcategory)
if a then
@@ -235,116 +252,127 @@ process = function(start) -- we cannot use the processor as we have no finalizer
setattr(start,a_tagged,start_tagged("ms")) -- mtext
end
stop_tagged()
+ -- showtag(start,id,false)
break
- elseif id == math_delim_code then
+ elseif id == delim_code then
-- check for code
setattr(start,a_tagged,start_tagged("mo"))
stop_tagged()
+ -- showtag(start,id,false)
break
- elseif id == math_style_code then
+ elseif id == style_code then
-- has a next
- elseif id == math_noad_code then
+ elseif id == noad_code then
+ -- setattr(start,a_tagged,tags.current())
processsubsup(start)
- elseif id == math_box_code or id == hlist_code or id == vlist_code then
- -- keep an eye on math_box_code and see what ends up in there
+ elseif id == dubbox_code or id == hlist_code or id == vlist_code then
+ -- keep an eye on subbox_code and see what ends up in there
local attr = getattr(start,a_tagged)
-if not attr then
- -- just skip
-else
- local specification = taglist[attr]
- if specification then
- local tag = specification.tagname
- if tag == "formulacaption" then
- -- skip
- elseif tag == "mstacker" then
- local list = getlist(start)
- if list then
- process(list)
- end
- else
- if tag ~= "mstackertop" and tag ~= "mstackermid" and tag ~= "mstackerbot" then
- tag = "mtext"
- end
- local text = start_tagged(tag)
- setattr(start,a_tagged,text)
- local list = getlist(start)
- if not list then
- -- empty list
- elseif not attr then
- -- box comes from strange place
- set_attributes(list,a_tagged,text) -- only the first node ?
+ if not attr then
+ -- just skip
+ else
+ local specification = taglist[attr]
+ if specification then
+ local tag = specification.tagname
+ if tag == "formulacaption" then
+ -- skip
+ elseif tag == "mstacker" then
+ local list = getlist(start)
+ if list then
+ process(list)
+ end
else
- -- Beware, the first node in list is the actual list so we definitely
- -- need to nest. This approach is a hack, maybe I'll make a proper
- -- nesting feature to deal with this at another level. Here we just
- -- fake structure by enforcing the inner one.
- --
- -- todo: have a local list with local tags that then get appended
- --
- local tagdata = specification.taglist
- local common = #tagdata + 1
- local function runner(list,depth) -- quite inefficient
- local cache = { } -- we can have nested unboxed mess so best local to runner
- local keep = nil
- -- local keep = { } -- win case we might need to move keep outside
- for n in traverse_nodes(list) do
- local id = getid(n)
- local mth = id == math_code and getsubtype(n)
- if mth == 0 then
- -- insert(keep,text)
- keep = text
- text = start_tagged("mrow")
- common = common + 1
- end
- local aa = getattr(n,a_tagged)
- if aa then
- local ac = cache[aa]
- if not ac then
- local tagdata = taglist[aa].taglist
- local extra = #tagdata
- if common <= extra then
- for i=common,extra do
- ac = restart_tagged(tagdata[i]) -- can be made faster
- end
- for i=common,extra do
- stop_tagged() -- can be made faster
+ if tag ~= "mstackertop" and tag ~= "mstackermid" and tag ~= "mstackerbot" then
+ tag = "mtext"
+ end
+ local text = start_tagged(tag)
+ setattr(start,a_tagged,text)
+ local list = getlist(start)
+ if not list then
+ -- empty list
+ elseif not attr then
+ -- box comes from strange place
+ set_attributes(list,a_tagged,text) -- only the first node ?
+ else
+ -- Beware, the first node in list is the actual list so we definitely
+ -- need to nest. This approach is a hack, maybe I'll make a proper
+ -- nesting feature to deal with this at another level. Here we just
+ -- fake structure by enforcing the inner one.
+ --
+ -- todo: have a local list with local tags that then get appended
+ --
+ local tagdata = specification.taglist
+ local common = #tagdata + 1
+ local function runner(list,depth) -- quite inefficient
+ local cache = { } -- we can have nested unboxed mess so best local to runner
+ local keep = nil
+ -- local keep = { } -- win case we might need to move keep outside
+ for n, id, subtype in nextnode, list do
+ local mth = id == math_code and subtype
+ if mth == 0 then -- hm left_code
+ -- insert(keep,text)
+ keep = text
+ text = start_tagged("mrow")
+ common = common + 1
+ end
+ local aa = getattr(n,a_tagged)
+ if aa then
+ local ac = cache[aa]
+ if not ac then
+ local tagdata = taglist[aa].taglist
+ local extra = #tagdata
+ if common <= extra then
+ for i=common,extra do
+ ac = restart_tagged(tagdata[i]) -- can be made faster
+ end
+ for i=common,extra do
+ stop_tagged() -- can be made faster
+ end
+ else
+ ac = text
end
- else
- ac = text
+ cache[aa] = ac
end
- cache[aa] = ac
+ setattr(n,a_tagged,ac)
+ else
+ setattr(n,a_tagged,text)
+ end
+ if id == hlist_code or id == vlist_code then
+ runner(getlist(n),depth+1)
+ elseif id == glyph_code then
+ -- this should not be needed
+ local components = getcomponents(n) -- unlikely set
+ if components then
+ runner(getcomponent,depth+1)
+ end
+ elseif id == disc_code then
+ -- this should not be needed
+ local pre, post, replace = getdisc(n)
+ if pre then
+ runner(pre,depth+1)
+ end
+ if post then
+ runner(post,depth+1)
+ end
+ if replace then
+ runner(replace,depth+1)
+ end
+ end
+ if mth == 1 then
+ stop_tagged()
+ -- text = remove(keep)
+ text = keep
+ common = common - 1
end
- setattr(n,a_tagged,ac)
- else
- setattr(n,a_tagged,text)
- end
-
- if id == hlist_code or id == vlist_code then
- runner(getlist(n),depth+1)
- elseif id == glyph_code then
- -- this should not be needed (todo: use tounicode info)
- runner(getcomponents(n),depth+1)
- elseif id == disc_code then
- local pre, post, replace = getdisc(n)
- runner(pre,depth+1) -- idem
- runner(post,depth+1) -- idem
- runner(replace,depth+1) -- idem
- end
- if mth == 1 then
- stop_tagged()
- -- text = remove(keep)
- text = keep
- common = common - 1
end
end
+ runner(list,0)
end
- runner(list,0)
+ stop_tagged()
end
- stop_tagged()
end
end
-end
- elseif id == math_sub_code then -- normally a hbox
+ elseif id == submlistcode then -- normally a hbox
local list = getlist(start)
if list then
local attr = getattr(start,a_tagged)
@@ -370,7 +398,7 @@ end
end
elseif tag == "mstacker" then -- or tag == "mstackertop" or tag == "mstackermid" or tag == "mstackerbot" then
-- looks like it gets processed twice
--- do we still end up here ?
+ -- do we still end up here ?
setattr(start,a_tagged,restart_tagged(attr)) -- so we just reuse the attribute
process(list)
stop_tagged()
@@ -385,7 +413,7 @@ end
stop_tagged()
end
end
- elseif id == math_fraction_code then
+ elseif id == fraction_code then
local num = getfield(start,"num")
local denom = getfield(start,"denom")
local left = getfield(start,"left")
@@ -404,7 +432,7 @@ end
process(right)
stop_tagged()
end
- elseif id == math_choice_code then
+ elseif id == choice_code then
local display = getfield(start,"display")
local text = getfield(start,"text")
local script = getfield(start,"script")
@@ -421,7 +449,7 @@ end
if scriptscript then
process(scriptscript)
end
- elseif id == math_fence_code then
+ elseif id == fence_code then
local delim = getfield(start,"delim")
local subtype = getfield(start,"subtype")
if subtype == 1 then
@@ -478,7 +506,7 @@ end
else
-- can't happen
end
- elseif id == math_radical_code then
+ elseif id == radical_code then
local left = getfield(start,"left")
local degree = getfield(start,"degree")
if left then
@@ -496,7 +524,7 @@ end
processsubsup(start)
stop_tagged()
end
- elseif id == math_accent_code then
+ elseif id == accent_code then
local accent = getfield(start,"accent")
local bot_accent = getfield(start,"bot_accent")
local subtype = getsubtype(start)
@@ -506,8 +534,8 @@ end
accent = true,
top = getunicode(accent),
bottom = getunicode(bot_accent),
- topfixed = subtype == math_fixed_top or subtype == math_fixed_both,
- bottomfixed = subtype == math_fixed_bottom or subtype == math_fixed_both,
+ topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code,
+ bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code,
}))
processsubsup(start)
process(bot_accent)
@@ -517,7 +545,7 @@ end
setattr(start,a_tagged,start_tagged("munder", {
accent = true,
bottom = getunicode(bot_accent),
- bottomfixed = subtype == math_fixed_bottom or subtype == math_fixed_both,
+ bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code,
}))
processsubsup(start)
process(bot_accent)
@@ -527,7 +555,7 @@ end
setattr(start,a_tagged,start_tagged("mover", {
accent = true,
top = getunicode(accent),
- topfixed = subtype == math_fixed_top or subtype == math_fixed_both,
+ topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code,
}))
processsubsup(start)
process(accent)
@@ -544,6 +572,7 @@ end
stop_tagged()
end
end
+-- showtag(start,id,false)
start = getnext(start)
end
if mtexttag then
@@ -552,12 +581,10 @@ end
end
function noads.handlers.tags(head,style,penalties)
- head = tonut(head)
- local v_mode = getattr(head,a_mathmode)
- local v_math = start_tagged("math", { mode = v_mode == 1 and "display" or "inline" })
+ start_tagged("math", { mode = (getattr(head,a_mathmode) == 1) and "display" or "inline" })
+-- start_tagged("mrow")
setattr(head,a_tagged,start_tagged("mrow"))
process(head)
stop_tagged()
stop_tagged()
- return true
end
diff --git a/tex/context/base/mkiv/math-vfu.lua b/tex/context/base/mkiv/math-vfu.lua
index 4767ffa90..ed6f69f41 100644
--- a/tex/context/base/mkiv/math-vfu.lua
+++ b/tex/context/base/mkiv/math-vfu.lua
@@ -46,9 +46,18 @@ fonts.encodings.math = mathencodings -- better is then: fonts.encodings.vecto
local vfmath = allocate()
fonts.handlers.vf.math = vfmath
+local helpers = fonts.helpers
+local vfcommands = helpers.commands
+local rightcommand = vfcommands.right
+local leftcommand = vfcommands.left
+local downcommand = vfcommands.down
+local upcommand = vfcommands.up
+local push = vfcommands.push
+local pop = vfcommands.pop
+
local shared = { }
--- local push, pop, back = { "push" }, { "pop" }, { "slot", 1, 0x2215 }
+-- local back = { "slot", 1, 0x2215 }
--
-- local function negate(main,characters,id,size,unicode,basecode)
-- if not characters[unicode] then
@@ -64,8 +73,8 @@ local shared = { }
-- commands = {
-- { "slot", 1, basecode },
-- push,
--- { "down", ht/5},
--- { "right", - wd/2},
+-- downcommand[ht/5],
+-- leftcommand[wd/2],
-- back,
-- push,
-- }
@@ -139,107 +148,96 @@ local function parent(main,characters,id,size,unicode,first,rule,last)
end
end
-local push, pop, step = { "push" }, { "pop" }, 0.2 -- 0.1 is nicer but gives larger files
+local step = 0.2 -- 0.1 is nicer but gives larger files
local function make(main,characters,id,size,n,m)
local old = 0xFF000 + n
- local c = characters[old]
+ local c = characters[old]
if c then
- local upslot, dnslot, uprule, dnrule = 0xFF100 + n, 0xFF200 + n, 0xFF300 + m, 0xFF400 + m
- local xu = main.parameters.x_height + 0.3*size
- local xd = 0.3*size
- local w, h, d = c.width, c.height, c.depth
+ local upslot = 0xFF100 + n
+ local dnslot = 0xFF200 + n
+ local uprule = 0xFF300 + m
+ local dnrule = 0xFF400 + m
+ local xu = main.parameters.x_height + 0.3*size
+ local xd = 0.3*size
+ local w = c.width or 0
+ local h = c.height or 0
+ local d = c.depth or 0
local thickness = h - d
local rulewidth = step*size -- we could use an overlap
- local slot = { "slot", id, old }
- local rule = { "rule", thickness, rulewidth }
- local up = { "down", -xu }
- local dn = { "down", xd }
- local ht, dp = xu + 3*thickness, 0
+ local slot = { "slot", id, old }
+ local rule = { "rule", thickness, rulewidth }
+ local up = upcommand[xu]
+ local dn = downcommand[xd]
+ local ht = xu + 3*thickness
+ local dp = 0
if not characters[uprule] then
- characters[uprule] = { width = rulewidth, height = ht, depth = dp, commands = { push, up, rule, pop } }
+ characters[uprule] = {
+ width = rulewidth,
+ height = ht,
+ depth = dp,
+ commands = { push, up, rule, pop },
+ }
end
- characters[upslot] = { width = w, height = ht, depth = dp, commands = { push, up, slot, pop } }
- local ht, dp = 0, xd + 3*thickness
+ characters[upslot] = {
+ width = w,
+ height = ht,
+ depth = dp,
+ commands = { push, up, slot, pop },
+ }
+ local ht = 0
+ local dp = xd + 3*thickness
if not characters[dnrule] then
- characters[dnrule] = { width = rulewidth, height = ht, depth = dp, commands = { push, dn, rule, pop } }
+ characters[dnrule] = {
+ width = rulewidth,
+ height = ht,
+ depth = dp,
+ commands = { push, dn, rule, pop }
+ }
end
- characters[dnslot] = { width = w, height = ht, depth = dp, commands = { push, dn, slot, pop } }
+ characters[dnslot] = {
+ width = w,
+ height = ht,
+ depth = dp,
+ commands = { push, dn, slot, pop },
+ }
end
end
local function clipped(main,characters,id,size,unicode,original) -- push/pop needed?
local minus = characters[original]
if minus then
- local mu = size/18
- local step = 3*mu
+ local mu = size/18
+ local step = 3*mu
local width = minus.width
if width > step then
width = width - step
- step = step / 2
+ step = step / 2
else
width = width / 2
- step = width
+ step = width
end
characters[unicode] = {
width = width,
height = minus.height,
depth = minus.depth,
- commands = { push, { "right", -step }, { "slot", id, original }, pop }
+ commands = {
+ push,
+ leftcommand[step],
+ { "slot", id, original },
+ pop,
+ }
}
end
end
--- fails: pdf:page: pdf:direct: ... some funny displacement
-
--- this does not yet work ... { "scale", 2, 0, 0, 3 } .. commented code
---
--- this does not work ... no interpretation going on here
---
--- local nodeinjections = backends.nodeinjections
--- { "node", nodeinjections.save() },
--- { "node", nodeinjections.transform(.7,0,0,.7) },
--- commands[#commands+1] = { "node", nodeinjections.restore() }
-
--- local done = { }
---
--- local function raise(main,characters,id,size,unicode,private,n,id_of_smaller) -- this is a real fake mess
--- local raised = characters[private]
--- if raised then
--- if not done[unicode] then
--- report_virtual("temporary too large %U due to issues in luatex backend",unicode)
--- done[unicode] = true
--- end
--- local up = 0.85 * main.parameters.x_height
--- local slot = { "slot", id, private }
--- local commands = {
--- push,
--- { "down", - up },
--- -- { "scale", .7, 0, 0, .7 },
--- slot,
--- }
--- for i=2,n do
--- commands[#commands+1] = slot
--- end
--- commands[#commands+1] = pop
--- characters[unicode] = {
--- width = .7 * n * raised.width,
--- height = .7 * (raised.height + up),
--- depth = .7 * (raised.depth - up),
--- commands = commands,
--- }
--- end
--- end
-
local function raise(main,characters,id,size,unicode,private,n,id_of_smaller) -- this is a real fake mess
local raised = fonts.hashes.characters[main.fonts[id_of_smaller].id][private] -- characters[private]
if raised then
- local up = 0.85 * main.parameters.x_height
+ local up = 0.85 * main.parameters.x_height
local slot = { "slot", id_of_smaller, private }
local commands = {
- push,
- { "down", - up },
- slot,
+ push, upcommand[up], slot,
}
for i=2,n do
commands[#commands+1] = slot
@@ -258,65 +256,85 @@ end
local function dots(main,characters,id,size,unicode)
local c = characters[0x002E]
if c then
- local w, h, d = c.width, c.height, c.depth
- local mu = size/18
- local right3mu = { "right", 3*mu }
- local right1mu = { "right", 1*mu }
- local up1size = { "down", -.1*size }
- local up4size = { "down", -.4*size }
- local up7size = { "down", -.7*size }
- local right2muw = { "right", 2*mu + w }
- local slot = { "slot", id, 0x002E }
+ local w = c.width
+ local h = c.height
+ local d = c.depth
+ local mu = size/18
+ local right3mu = rightcommand[3*mu]
+ local right1mu = rightcommand[1*mu]
+ local up1size = upcommand[.1*size]
+ local up4size = upcommand[.4*size]
+ local up7size = upcommand[.7*size]
+ local right2muw = rightcommand[2*mu + w]
+ local slot = { "slot", id, 0x002E }
if unicode == 0x22EF then
local c = characters[0x022C5]
if c then
- local w, h, d = c.width, c.height, c.depth
- local slot = { "slot", id, 0x022C5 }
+ local width = c.width
+ local height = c.height
+ local depth = c.depth
+ local slot = { "slot", id, 0x022C5 }
characters[unicode] = {
- width = 3*w + 2*3*mu, height = h, depth = d,
- commands = { push, slot, right3mu, slot, right3mu, slot, pop }
+ width = 3*width + 2*3*mu,
+ height = height,
+ depth = depth,
+ commands = {
+ push, slot, right3mu, slot, right3mu, slot, pop,
+ }
}
end
elseif unicode == 0x22EE then
-- weird height !
characters[unicode] = {
- width = w, height = h+(1.4)*size, depth = 0,
- commands = { push, push, slot, pop, up4size, push, slot, pop, up4size, slot, pop }
+ width = w,
+ height = h+(1.4)*size,
+ depth = 0,
+ commands = {
+ push, push, slot, pop, up4size, push, slot, pop, up4size, slot, pop,
+ }
}
elseif unicode == 0x22F1 then
characters[unicode] = {
- width = 3*w + 6*size/18, height = 1.5*size, depth = 0,
+ width = 3*w + 6*size/18,
+ height = 1.5*size,
+ depth = 0,
commands = {
push,
- right1mu,
- push, up7size, slot, pop,
- right2muw,
- push, up4size, slot, pop,
- right2muw,
- push, up1size, slot, pop,
- right1mu,
+ right1mu,
+ push, up7size, slot, pop,
+ right2muw,
+ push, up4size, slot, pop,
+ right2muw,
+ push, up1size, slot, pop,
+ right1mu,
pop
}
}
elseif unicode == 0x22F0 then
characters[unicode] = {
- width = 3*w + 6*size/18, height = 1.5*size, depth = 0,
+ width = 3*w + 6*size/18,
+ height = 1.5*size,
+ depth = 0,
commands = {
push,
- right1mu,
- push, up1size, slot, pop,
- right2muw,
- push, up4size, slot, pop,
- right2muw,
- push, up7size, slot, pop,
- right1mu,
+ right1mu,
+ push, up1size, slot, pop,
+ right2muw,
+ push, up4size, slot, pop,
+ right2muw,
+ push, up7size, slot, pop,
+ right1mu,
pop
}
}
else
characters[unicode] = {
- width = 3*w + 2*3*mu, height = h, depth = d,
- commands = { push, slot, right3mu, slot, right3mu, slot, pop }
+ width = 3*w + 2*3*mu,
+ height = h,
+ depth = d,
+ commands = {
+ push, slot, right3mu, slot, right3mu, slot, pop,
+ }
}
end
end
@@ -331,21 +349,23 @@ local function vertbar(main,characters,id,size,parent,scale,unicode)
width = cp.width,
height = cp.height + sc,
depth = cp.depth + sc,
+ next = cp.next, -- can be extensible
commands = {
- push, { "down", -sc }, pc, pop,
- push, { "down", sc }, pc, pop,
+ push, upcommand [sc], pc, pop,
+ push, downcommand[sc], pc, pop,
pc,
},
- next = cp.next -- can be extensible
}
cp.next = unicode
end
end
local function jointwo(main,characters,id,size,unicode,u1,d12,u2,what)
- local c1, c2 = characters[u1], characters[u2]
+ local c1 = characters[u1]
+ local c2 = characters[u2]
if c1 and c2 then
- local w1, w2 = c1.width, c2.width
+ local w1 = c1.width
+ local w2 = c2.width
local mu = size/18
characters[unicode] = {
width = w1 + w2 - d12 * mu,
@@ -353,7 +373,7 @@ local function jointwo(main,characters,id,size,unicode,u1,d12,u2,what)
depth = max(c1.depth or 0, c2.depth or 0),
commands = {
{ "slot", id, u1 },
- { "right", -d12*mu } ,
+ leftcommand[d12*mu],
{ "slot", id, u2 },
},
}
@@ -361,19 +381,23 @@ local function jointwo(main,characters,id,size,unicode,u1,d12,u2,what)
end
local function jointhree(main,characters,id,size,unicode,u1,d12,u2,d23,u3)
- local c1, c2, c3 = characters[u1], characters[u2], characters[u3]
+ local c1 = characters[u1]
+ local c2 = characters[u2]
+ local c3 = characters[u3]
if c1 and c2 and c3 then
- local w1, w2, w3 = c1.width, c2.width, c3.width
+ local w1 = c1.width
+ local w2 = c2.width
+ local w3 = c3.width
local mu = size/18
characters[unicode] = {
width = w1 + w2 + w3 - d12*mu - d23*mu,
height = max(c1.height or 0, c2.height or 0, c3.height or 0),
- depth = max(c1.depth or 0, c2.depth or 0, c3.depth or 0),
+ depth = max(c1.depth or 0, c2.depth or 0, c3.depth or 0),
commands = {
{ "slot", id, u1 },
- { "right", - d12*mu } ,
+ leftcommand[d12*mu],
{ "slot", id, u2 },
- { "right", - d23*mu },
+ leftcommand[d23*mu],
{ "slot", id, u3 },
}
}
@@ -381,24 +405,32 @@ local function jointhree(main,characters,id,size,unicode,u1,d12,u2,d23,u3)
end
local function stack(main,characters,id,size,unicode,u1,d12,u2)
- local c1, c2 = characters[u1], characters[u2]
- if c1 and c2 then
- local w1, w2 = c1.width, c2.width
- local h1, h2 = c1.height, c2.height
- local d1, d2 = c1.depth, c2.depth
- local mu = size/18
- characters[unicode] = {
- width = w1,
- height = h1 + h2 + d12,
- depth = d1,
- commands = {
- { "slot", id, u1 },
- { "right", - w1/2 - w2/2 } ,
- { "down", -h1 + d2 -d12*mu } ,
- { "slot", id, u2 },
- }
- }
+ local c1 = characters[u1]
+ if not c1 then
+ return
+ end
+ local c2 = characters[u2]
+ if not c2 then
+ return
end
+ local w1 = c1.width or 0
+ local h1 = c1.height or 0
+ local d1 = c1.depth or 0
+ local w2 = c2.width or 0
+ local h2 = c2.height or 0
+ local d2 = c2.depth or 0
+ local mu = size/18
+ characters[unicode] = {
+ width = w1,
+ height = h1 + h2 + d12,
+ depth = d1,
+ commands = {
+ { "slot", id, u1 },
+ leftcommand[w1/2 + w2/2],
+ downcommand[-h1 + d2 -d12*mu],
+ { "slot", id, u2 },
+ }
+ }
end
local function repeated(main,characters,id,size,unicode,u,n,private,fraction) -- math-fbk.lua
@@ -406,16 +438,14 @@ local function repeated(main,characters,id,size,unicode,u,n,private,fraction) --
if c then
local width = c.width
local italic = fraction*width -- c.italic or 0 -- larger ones have funny italics
- local tc = { "slot", id, u }
- local tr = { "right", -italic } -- see hack elsewhere
+ local tc = { "slot", id, u }
+ local tr = leftcommand[italic] -- see hack elsewhere
local commands = { }
for i=1,n-1 do
commands[#commands+1] = tc
commands[#commands+1] = tr
end
commands[#commands+1] = tc
--- inspect(c)
--- inspect(commands)
local next = c.next
if next then
repeated(main,characters,id,size,private,next,n,private+1,fraction)
@@ -589,7 +619,8 @@ setmetatableindex(reverse, function(t,name)
if trace_virtual then
report_virtual("initializing math vector %a",name)
end
- local m, r = mathencodings[name], { }
+ local m = mathencodings[name]
+ local r = { }
for u, i in next, m do
r[i] = u
end
@@ -597,6 +628,10 @@ setmetatableindex(reverse, function(t,name)
return r
end)
+-- use char and font hash
+--
+-- commands = { { "font", slot }, { "char", unicode } },
+
local function copy_glyph(main,target,original,unicode,slot)
local addprivate = fonts.helpers.addprivate
local olddata = original[unicode]
@@ -623,7 +658,6 @@ local function copy_glyph(main,target,original,unicode,slot)
}
local newnextglyph = addprivate(main,formatters["M-N-%H"](nextglyph),newnextdata)
newdata.next = newnextglyph
--- report_virtual("copied next: %X",newdata.next)
local nextnextglyph = oldnextdata.next
if nextnextglyph == nextglyph then
break
@@ -649,7 +683,6 @@ local function copy_glyph(main,target,original,unicode,slot)
commands = { { "slot", slot, oldglyph } },
}
hvi.glyph = addprivate(main,formatters["M-H-%H"](oldglyph),newdata)
--- report_virtual("copied h variant: %X at index %i",hvi.glyph,i)
end
end
local vv = olddata.vert_variants
@@ -668,7 +701,6 @@ local function copy_glyph(main,target,original,unicode,slot)
commands = { { "slot", slot, oldglyph } },
}
vvi.glyph = addprivate(main,formatters["M-V-%H"](oldglyph),newdata)
--- report_virtual("copied v variant: %X at index %i",vvi.glyph,i)
end
end
return newdata
@@ -678,13 +710,17 @@ end
vfmath.copy_glyph = copy_glyph
function vfmath.define(specification,set,goodies)
- local name = specification.name -- symbolic name
- local size = specification.size -- given size
- local loaded, fontlist, names, main = { }, { }, { }, nil
- local start = (trace_virtual or trace_timings) and os.clock()
- local okset, n = { }, 0
+ local name = specification.name -- symbolic name
+ local size = specification.size -- given size
+ local loaded = { }
+ local fontlist = { }
+ local names = { }
+ local main = nil
+ local start = (trace_virtual or trace_timings) and os.clock()
+ local okset = { }
+ local n = 0
for s=1,#set do
- local ss = set[s]
+ local ss = set[s]
local ssname = ss.name
if add_optional and ss.optional then
if trace_virtual then
@@ -828,11 +864,11 @@ function vfmath.define(specification,set,goodies)
elseif add_optional and ss.optional then
-- skip, redundant
else
- local newparameters = fs.parameters
+ local newparameters = fs.parameters
local newmathparameters = fs.mathparameters
if newmathparameters then
if not parameters_done or ss.parameters then
- mathparameters = newmathparameters
+ mathparameters = newmathparameters
parameters_done = true
end
elseif not newparameters then
@@ -867,7 +903,7 @@ function vfmath.define(specification,set,goodies)
-- report_virtual("loading and virtualizing font %a at size %p, setting sy parameters",name,size)
end
if ss.overlay then
- local fc = fs.characters
+ local fc = fs.characters
local first = ss.first
if first then
local last = ss.last or first
@@ -882,12 +918,14 @@ function vfmath.define(specification,set,goodies)
else
local vectorname = ss.vector
if vectorname then
- local offset = 0xFF000
- local vector = mathencodings[vectorname]
- local rotcev = reverse[vectorname]
+ local offset = 0xFF000
+ local vector = mathencodings[vectorname]
+ local rotcev = reverse[vectorname]
local isextension = ss.extension
if vector and rotcev then
- local fc, fd, si = fs.characters, fs.descriptions, shared[s]
+ local fc = fs.characters
+ local fd = fs.descriptions
+ local si = shared[s]
local skewchar = ss.skewchar
for unicode, index in next, vector do
local fci = fc[index]
@@ -913,8 +951,8 @@ function vfmath.define(specification,set,goodies)
ref = { { 'slot', s, index } }
si[index] = ref
end
- local kerns = fci.kerns
- local width = fci.width
+ local kerns = fci.kerns
+ local width = fci.width
local italic = fci.italic
if italic and italic > 0 then
-- int_a^b
diff --git a/tex/context/base/mkiv/meta-blb.lua b/tex/context/base/mkiv/meta-blb.lua
new file mode 100644
index 000000000..e1c0de74f
--- /dev/null
+++ b/tex/context/base/mkiv/meta-blb.lua
@@ -0,0 +1,322 @@
+if not modules then modules = { } end modules ['meta-blb'] = {
+ version = 1.001,
+ comment = "companion to mlib-ctx.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- This could be integrated in other modules but for me it also serves
+-- as an example of usign the plugin mechanism.
+
+local tonumber = tonumber
+
+local setmetatableindex = table.setmetatableindex
+local insert, remove = table.insert, table.remove
+local formatters = string.formatters
+
+local topoints = number.topoints
+local mpprint = mp.print
+local mpinteger = mp.integer
+local mppoints = mp.points
+local mptriplet = mp.triplet
+local mptripletpoints = mp.tripletpoints
+
+local nuts = nodes.nuts
+local hpack = nuts.hpack
+local setbox = nuts.setbox
+local getwhd = nuts.getwhd
+local getwidth = nuts.getwidth
+local toutf = nuts.toutf
+
+local trace = false
+local report = logs.reporter("metapost","blobs")
+
+trackers.register("metapost.blobs", function(v) trace = v end)
+
+local allblobs = { }
+
+local function newcategory(t,k)
+ if trace then
+ report("new category %a",k)
+ end
+ local v = {
+ name = k,
+ text = "",
+ blobs = { },
+ }
+ t[k] = v
+ return v
+end
+
+local texblobs = setmetatableindex(newcategory)
+
+local function blob_raw_reset(category)
+ -- we need to keep the allblobs
+ if category then
+ if trace then
+ report("reset category %a",category)
+ end
+ texblobs[category] = nil
+ else
+ if trace then
+ report("reset all")
+ end
+ texblobs = setmetatableindex(newcategory)
+ end
+end
+
+local function blob_raw_dimensions(i)
+ local blob = allblobs[i]
+ if blob then
+ return getwhd(blob)
+ else
+ return 0, 0, 0
+ end
+end
+
+local function blob_raw_content(i)
+ return allblobs[i]
+end
+
+local function blob_raw_toutf(i)
+ return toutf(allblobs[i])
+end
+
+local function blob_raw_wipe(i)
+ allblobs[i] = false
+end
+
+mp.mf_blob_raw_dimensions = blob_raw_dimensions
+mp.mf_blob_raw_content = blob_raw_content
+mp.mf_blob_raw_reset = blob_raw_reset
+mp.mf_blob_raw_wipe = blob_raw_wipe
+mp.mf_blob_raw_toutf = blob_raw_toutf
+
+function mp.mf_blob_new(category,text)
+ if trace then
+ report("category %a, text %a",category,text)
+ end
+ texblobs[category].text = text
+end
+
+function mp.mf_blob_add(category,blob)
+ local tb = texblobs[category].blobs
+ local tn = #allblobs + 1
+ blob = hpack(blob)
+ allblobs[tn] = blob
+ tb[#tb+1] = tn
+ if trace then
+ report("category %a, blob %a set, content %a",category,tn,blob_raw_toutf(tn))
+ end
+end
+
+function mp.mf_blob_width(category,i)
+ local index = texblobs[category].blobs[i]
+ local blob = allblobs[index]
+ if blob then
+ mppoints(getwidth(blob) or 0)
+ else
+ mpinteger(0)
+ end
+end
+
+function mp.mf_blob_size(category,i)
+ mpprint(#texblobs[category].blobs or 0)
+end
+
+function mp.mf_blob_index(category,i)
+ mpprint(texblobs[category].blobs[i] or 0)
+end
+
+function mp.mf_blob_dimensions(category,i)
+ local index = texblobs[category].blobs[i]
+ local blob = allblobs[index]
+ if blob then
+ mptripletpoints(getwhd(blob))
+ else
+ mptriplet(0,0,0)
+ end
+end
+
+local sxsy = metapost.sxsy
+local cm = metapost.cm
+
+local f_f = formatters["%.6F"]
+
+directives.register("pdf.stripzeros",function()
+ f_f = formatters["%.6N"]
+end)
+
+local function injectblob(object,blob)
+ local sx, rx, ry, sy, tx, ty = cm(object)
+ local wd, ht, dp = blob_raw_dimensions(blob)
+ if wd then
+ object.path = false
+ object.color = false
+ object.grouped = true
+ object.istext = true
+ return function()
+ if trace then
+ report("injecting blob %a, width %p, heigth %p, depth %p, text %a",blob,wd,ht,dp,blob_raw_toutf(blob))
+ end
+ context.MPLIBgetblobscaledcm(blob,
+ f_f(sx), f_f(rx), f_f(ry),
+ f_f(sy), f_f(tx), f_f(ty),
+ sxsy(wd,ht,dp))
+ end
+ end
+end
+
+-- mp.mf_blob_inject = injectblob
+
+local function getblob(box,blob)
+ setbox(box,blob_raw_content(blob))
+ blob_raw_wipe(blob)
+end
+
+interfaces.implement {
+ name = "mpgetblob",
+ actions = getblob,
+ arguments = { "integer", "integer" },
+}
+
+-- the plug:
+
+
+local function reset()
+ blob_raw_reset()
+end
+
+local function process(object,prescript,before,after)
+-- if prescript.tb_stage == "inject" then
+ local tb_blob = tonumber(prescript.tb_blob)
+ if tb_blob then
+ before[#before+1] = injectblob(object,tb_blob)
+ end
+-- end
+end
+
+metapost.installplugin {
+ name = "texblob",
+ reset = reset,
+ process = process,
+}
+
+-- Here follows an example of usage of the above: a more modern
+-- version of followokens (in meta-imp-txt.mkiv).
+
+local nodecodes = nodes.nodecodes
+local kerncodes = nodes.kerncodes
+
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+
+local fontkern_code = kerncodes.fontkern
+local italickern_code = kerncodes.italickern
+
+local a_fontkern = attributes.private("fontkern")
+
+local nuts = nodes.nuts
+local takebox = nuts.takebox
+local getlist = nuts.getlist
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local getnext = nuts.getnext
+local flatten_list = nuts.flatten_discretionaries
+local remove_node = nuts.remove
+local flush_node = nuts.flush
+
+local addblob = mp.mf_blob_add
+local newblob = mp.mf_blob_new
+
+local visible_codes = {
+ [nodecodes.glyph] = true,
+ [nodecodes.glue] = true,
+ [nodecodes.hlist] = true,
+ [nodecodes.vlist] = true,
+ [nodecodes.rule] = true,
+}
+
+local function initialize(category,box)
+ local wrap = takebox(box)
+ if wrap then
+ local head = getlist(wrap)
+ local tail = nil
+ local temp = nil
+ if head then
+ local n = { }
+ local s = 0
+ head = flatten_list(head)
+ local current = head
+ while current do
+ local id = getid(current)
+ if visible_codes[id] then
+ head, current, tail = remove_node(head,current)
+ s = s + 1
+ n[s] = tail
+ elseif id == kern_code then
+ local subtype = getsubtype(current)
+ if subtype == fontkern_code or subtype == italickern_code then -- or current[a_fontkern]
+ head, current, temp = remove_node(head,current)
+ setlink(tail,temp)
+ else
+ head, current, temp = remove_node(head,current)
+ s = s + 1
+ n[s] = temp
+ end
+ elseif id == glue_code then
+ head, current, temp = remove_node(head,current)
+ s = s + 1
+ n[s] = temp
+ else
+ current = getnext(current)
+ end
+ end
+ for i=1,s do
+ n[i] = addblob(category,n[i])
+ end
+ setlist(wrap,head)
+ end
+ flush_node(wrap)
+ end
+end
+
+interfaces.implement {
+ name = "MPLIBconvertfollowtext",
+ arguments = { "integer","integer" },
+ actions = initialize,
+}
+
+local mp_category = 0
+local mp_str = ""
+
+function mp.mf_inject_blob(category,str)
+ newblob(category,str) -- only for tracing
+ mp_category = category
+ mp_str = str
+ tex.runtoks("mpblobtext")
+end
+
+interfaces.implement {
+ name = "mpblobtext",
+ actions = function()
+ context.MPLIBfollowtext(mp_category,mp_str)
+ end
+}
+
+local process = function(object,prescript,before,after)
+ if prescript.ft_category then
+ object.path = false
+ object.color = false
+ object.grouped = true
+ object.istext = true
+ end
+end
+
+metapost.installplugin {
+ name = "followtext",
+ process = process,
+}
diff --git a/tex/context/base/mkiv/meta-blb.mkiv b/tex/context/base/mkiv/meta-blb.mkiv
new file mode 100644
index 000000000..4a5381dfc
--- /dev/null
+++ b/tex/context/base/mkiv/meta-blb.mkiv
@@ -0,0 +1,56 @@
+%D \module
+%D [ file=meta-blb,
+%D version=2018.04.12,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Blobs,
+%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 / Blobs}
+
+\registerctxluafile{meta-blb}{}
+
+\unprotect
+
+\unexpanded\def\MPLIBgetblobscaledcm#1#2#3#4#5#6#7#8#9%
+ {\clf_mpgetblob\MPtextbox#1\relax
+ \setbox\MPbox\hpack\bgroup
+ \dotransformnextbox{#2}{#3}{#4}{#5}{#6}{#7}%
+ \vpack to \zeropoint\bgroup
+ \vss
+ \hpack to \zeropoint \bgroup
+ % \fastsxsy{#8}{#9}{\raise\dp\MPtextbox\box\MPtextbox}%
+ \fastsxsy{#8}{#9}{\box\MPtextbox}%
+ \hss
+ \egroup
+ \egroup
+ \egroup
+ \smashbox\MPbox
+ \box\MPbox}
+
+%D An example of usage:
+
+\definefontfeature[followtext][liga=no]
+
+\unexpanded\def\MPLIBfollowtext#1#2%
+ {\begingroup
+ \scratchcounter#1\relax
+ \setbox\scratchbox\hbox{\addff{followtext}#2}%
+ \clf_MPLIBconvertfollowtext\scratchcounter\scratchbox
+ \endgroup}
+
+% \def\reversedtext#1%
+% {\cldcontext{table.concat(table.reverse(utf.totable(\!!bs#1\!!es)))}}
+
+%D New:
+
+\newtoks\mpblobtext
+
+\mpblobtext{\global\setbox\mptextbox\vbox{\clf_mpblobtext}}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/meta-fnt.lua b/tex/context/base/mkiv/meta-fnt.lua
index d061c926a..69212d08c 100644
--- a/tex/context/base/mkiv/meta-fnt.lua
+++ b/tex/context/base/mkiv/meta-fnt.lua
@@ -108,19 +108,17 @@ local function process(mpxformat,name,instances,scalefactor)
for i=1,instances do
characters = { }
descriptions = { }
- metapost.process(
- mpxformat,
- {
+ metapost.process {
+ mpx = mpxformat,
+ flusher = flusher,
+ askedfig = "all",
+ -- incontext = false,
+ data = {
formatters["randomseed := %s ;"](i*10),
formatters["charscale := %s ;"](scalefactor),
data,
},
- false,
- flusher,
- false,
- false,
- "all"
- )
+ }
lists[i] = {
characters = characters,
descriptions = descriptions,
@@ -191,9 +189,9 @@ statistics.register("metapost font generation", function()
if total > 0 then
local time = statistics.elapsedtime(flusher)
if total > 0 then
- return format("%i glyphs, %.3f seconds runtime, %.1f glyphs/second", total, time, total/time)
+ return format("%i glyphs, %s seconds runtime, %.1f glyphs/second", total, time, total/tonumber(time))
else
- return format("%i glyphs, %.3f seconds runtime", total, time)
+ return format("%i glyphs, %s seconds runtime", total, time)
end
end
end)
@@ -202,9 +200,9 @@ statistics.register("metapost font loading",function()
if variants > 0 then
local time = statistics.elapsedtime(metapost.fonts)
if variants > 0 then
- return format("%.3f seconds, %i instances, %.3f instances/second", time, variants, variants/time)
+ return format("%s seconds, %i instances, %.3f instances/second", time, variants, variants/tonumber(time))
else
- return format("%.3f seconds, %i instances", time, variants)
+ return format("%s seconds, %i instances", time, variants)
end
end
end)
diff --git a/tex/context/base/mkiv/meta-imp-dum.mkiv b/tex/context/base/mkiv/meta-imp-dum.mkiv
index e6ccc234c..481afe82a 100644
--- a/tex/context/base/mkiv/meta-imp-dum.mkiv
+++ b/tex/context/base/mkiv/meta-imp-dum.mkiv
@@ -59,7 +59,7 @@
% clip currentpicture to p ;
% \stopuseMPgraphic
-\startuseMPgraphic{figure:placeholder}{width,height,reduction,color}
+\startuseMPgraphic{minifun::figure:placeholder}{width,height,reduction,color}
begingroup ;
save w, h, d, r, p, c, b ;
numeric w, h, d, r ; path p ;
@@ -88,7 +88,7 @@
\defineoverlay
[figure:placeholder:graphic]
[\useMPgraphic
- {figure:placeholder}%
+ {minifun::figure:placeholder}%
{width=\figurewidth,%
height=\figureheight,%
reduction=\externalfigureparameter\c!reduction,%
diff --git a/tex/context/base/mkiv/meta-imp-mat.mkiv b/tex/context/base/mkiv/meta-imp-mat.mkiv
index 19a5ba385..495864a9e 100644
--- a/tex/context/base/mkiv/meta-imp-mat.mkiv
+++ b/tex/context/base/mkiv/meta-imp-mat.mkiv
@@ -15,8 +15,16 @@
%
% / for cambria
-\startMPextensions
+%D We need this for Alan, who nests math in \METAPOST:
+
+\unprotect
+
+\setupmathstackers
+ [\c!mp=minifun::math:stacker:\number\scratchunicode]
+\protect
+
+\startMPextensions
vardef math_stacker_bracket_shape(expr delta, rotate) =
image (
draw
@@ -129,55 +137,55 @@
enddef ;
\stopMPextensions
-\startuniqueMPgraphic{math:stacker:\number"FE3B4}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"FE3B4}{axis,ex,em}
math_stacker_draw_accent(math_stacker_bracket_shape(OverlayHeight,false)) ;
\stopuniqueMPgraphic
-\startuniqueMPgraphic{math:stacker:\number"FE3B5}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"FE3B5}{axis,ex,em}
math_stacker_draw_accent(math_stacker_bracket_shape(OverlayDepth,true)) ;
\stopuniqueMPgraphic
-\startuniqueMPgraphic{math:stacker:\number"FE3DC}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"FE3DC}{axis,ex,em}
math_stacker_draw_accent(math_stacker_parent_shape(OverlayHeight,false)) ;
\stopuniqueMPgraphic
-\startuniqueMPgraphic{math:stacker:\number"FE3DD}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"FE3DD}{axis,ex,em}
math_stacker_draw_accent(math_stacker_parent_shape(OverlayDepth,true)) ;
\stopuniqueMPgraphic
-\startuniqueMPgraphic{math:stacker:\number"FE3DE}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"FE3DE}{axis,ex,em}
math_stacker_draw_accent(math_stacker_brace_shape(OverlayHeight,false)) ;
\stopuniqueMPgraphic
-\startuniqueMPgraphic{math:stacker:\number"FE3DF}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"FE3DF}{axis,ex,em}
math_stacker_draw_accent(math_stacker_brace_shape(OverlayDepth,true)) ;
\stopuniqueMPgraphic
-\startuniqueMPgraphic{math:stacker:\number"FE33E}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"FE33E}{axis,ex,em}
math_stacker_draw_accent(math_stacker_bar_shape(false)) ;
\stopuniqueMPgraphic
-\startuniqueMPgraphic{math:stacker:\number"FE33F}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"FE33F}{axis,ex,em}
math_stacker_draw_accent(math_stacker_bar_shape(true)) ;
\stopuniqueMPgraphic
-\startuniqueMPgraphic{math:stacker:\number"2190}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"2190}{axis,ex,em}
math_stacker_draw_arrow(math_stacker_arrow_shape(\MPvar{axis},\MPvar{ex},\MPvar{em},false)) ;
\stopuniqueMPgraphic
-\startuniqueMPgraphic{math:stacker:\number"2192}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"2192}{axis,ex,em}
math_stacker_draw_arrow(math_stacker_arrow_shape(\MPvar{axis},\MPvar{ex},\MPvar{em},true)) ;
\stopuniqueMPgraphic
-\startuniqueMPgraphic{math:stacker:\number"2194}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"2194}{axis,ex,em}
math_stacker_draw_arrow(math_stacker_leftrightarrow_shape(\MPvar{axis},\MPvar{ex},\MPvar{em},false)) ;
\stopuniqueMPgraphic
-\startuniqueMPgraphic{math:stacker:\number"27F7}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"27F7}{axis,ex,em}
math_stacker_draw_arrow(math_stacker_leftrightarrow_shape(\MPvar{axis},\MPvar{ex},\MPvar{em},false)) ;
\stopuniqueMPgraphic
-\startuniqueMPgraphic{math:stacker:\number"21C4}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:stacker:\number"21C4}{axis,ex,em}
math_stacker_draw_arrow(math_stacker_rightoverleftarrow_shape(\MPvar{axis},\MPvar{ex},\MPvar{em},false)) ;
\stopuniqueMPgraphic
@@ -193,7 +201,7 @@
enddef ;
\stopMPextensions
-\startuniqueMPgraphic{math:radical:default}{axis,ex,em}
+\startuniqueMPgraphic{minifun::math:radical:default}{axis,ex,em}
draw
math_radical_simple(OverlayWidth,OverlayHeight,OverlayDepth,OverlayOffset)
withpen pencircle xscaled (2OverlayLineWidth) yscaled (3OverlayLineWidth/4) rotated 30
diff --git a/tex/context/base/mkiv/meta-imp-txt.mkiv b/tex/context/base/mkiv/meta-imp-txt.mkiv
index e9660b3a7..d4329cd6f 100644
--- a/tex/context/base/mkiv/meta-imp-txt.mkiv
+++ b/tex/context/base/mkiv/meta-imp-txt.mkiv
@@ -202,7 +202,10 @@
\stopMPdefinitions
\startluacode
+ local context = context
+
local nodecodes = nodes.nodecodes
+ local kerncodes = nodes.kerncodes
local visible_code = {
[nodecodes.glyph] = true,
@@ -212,72 +215,66 @@
[nodecodes.rule] = true,
}
- local disc_code = nodecodes.disc
- local kern_code = nodecodes.kern
-
- local c_userkern = nodes.kerncodes.userkern
+ local kern_code = nodecodes.kern
+ local c_userkern = kerncodes.userkern
local a_fontkern = attributes.private("fontkern")
+ local copynode = nodes.copy
+ local freenode = nodes.free
+
+ local topoints = number.topoints
+ local mpprint = mp.print
+
local n = nil
local s = 0
function mp.follow_reset()
- r = nil
+ for i=1,#n do
+ freenode(n[i])
+ end
+ n = nil
s = 0
end
function mp.follow_initialize(b)
- if not r then
- local l = tex.takebox(b).list
- n = { }
- s = 0
- while l do
- local c = l
- l = l.next
- local id = c.id
- if visible_code[id] then
- s = s + 1
- n[s] = c
- c.prev = nil
- c.next = nil
- elseif id == kern_code then
- if c.subtype == c_userkern and not c[a_fontkern] then
+ if not n then
+ local head = tex.takebox(b).list
+ if head then
+ n = { }
+ s = 0
+ head = node.flatten_discretionaries(head)
+ local current = head
+ while current do
+ local id = current.id
+ if visible_code[id] then
s = s + 1
- n[s] = c
- c.prev = nil
- else
- n[s].next = c
- c.prev = n[s]
- end
- c.next = nil
- elseif id == disc_code then
- local r = c.replace
- while r do
+ head, current, n[s] = nodes.remove(head,current)
+ elseif id == kern_code and current.subtype == c_userkern and not current[a_fontkern] then
s = s + 1
- n[s] = r
- r = r.next
- r.prev = nil
- r.next = nil
+ head, current, n[s] = nodes.remove(head,current)
+ else
+ current = current.next
end
end
+ nodes.flush_list(head)
end
end
end
function mp.follow_size()
- mp.print(s)
+ mpprint(s)
end
function mp.follow_slot(i)
- mp.print('textext("\\getfollowtoken{' .. i .. '}")')
+ mpprint('textext("\\getfollowtoken{' .. i .. '}")')
end
function mp.follow_text(s)
- context(n[s])
+ context(copynode(n[s]))
end
function mp.follow_width(i)
- mp.print(number.topoints(n[i].width))
+ mpprint(topoints(n[i].width))
end
\stopluacode
@@ -373,9 +370,8 @@
[medium]
\startuniqueMPgraphic{EnglishRule}{height,width,color}
- height = \MPvar{height} ;
x1 = 0 ; x3 = \MPvar{width} ; x2 = x4 = .5x3 ;
- y1 = y3 = 0 ; y2 = -y4 = height/2 ;
+ y1 = y3 = 0 ; y2 = -y4 = \MPvar{height}/2 ;
fill z1..z2..z3 & z3..z4..z1 & cycle withcolor \MPvar{color} ;
\stopuniqueMPgraphic
diff --git a/tex/context/base/mkiv/meta-ini.lua b/tex/context/base/mkiv/meta-ini.lua
index 6c4768671..f320efe20 100644
--- a/tex/context/base/mkiv/meta-ini.lua
+++ b/tex/context/base/mkiv/meta-ini.lua
@@ -117,23 +117,23 @@ do
local data = false
- function mp.start_saving_data(n)
+ function mp.mf_start_saving_data(n)
data = { }
end
- function mp.stop_saving_data()
+ function mp.mf_stop_saving_data()
if data then
-- nothing
end
end
- function mp.finish_saving_data()
+ function mp.mf_finish_saving_data()
if data then
-- nothing
end
end
- function mp.save_data(str)
+ function mp.mf_save_data(str)
if data then
data[#data+1] = str
end
diff --git a/tex/context/base/mkiv/meta-ini.mkiv b/tex/context/base/mkiv/meta-ini.mkiv
index 61e3523e6..89c7699de 100644
--- a/tex/context/base/mkiv/meta-ini.mkiv
+++ b/tex/context/base/mkiv/meta-ini.mkiv
@@ -97,7 +97,7 @@
\ifx\currentMPinstance\empty
\let\currentMPinstance\defaultMPinstance
\fi
- \global\t_meta_definitions\expandafter{\the\t_meta_definitions#2}%
+ \gtoksapp\t_meta_definitions{#2}%
\let\currentMPinstance\m_meta_saved_instance}
\let\stopMPdefinitions\relax
@@ -111,7 +111,7 @@
\let\stopMPextensions\relax
\unexpanded\def\startMPinitializations#1\stopMPinitializations % for all instances, when enabled
- {\global\t_meta_initializations\expandafter{\the\t_meta_initializations#1}}
+ {\gtoksapp\t_meta_initializations{#1}}
\let\stopMPinitializations\relax
@@ -131,7 +131,7 @@
\ifx\m_meta_option\!!plustoken \else
\global\t_meta_inclusions\emptytoks
\fi
- \global\t_meta_inclusions\expandafter{\the\t_meta_inclusions#2}%
+ \gtoksapp\t_meta_inclusions{#2}%
\let\currentMPinstance\m_meta_saved_instance}
\let\stopMPinclusions\relax
@@ -152,7 +152,7 @@
\ifx\m_meta_option\!!plustoken \else
\global\t_meta_inclusions\emptytoks
\fi
- \global\t_meta_inclusions\expandafter{\the\t_meta_inclusions#2}%
+ \gtoksapp\t_meta_inclusions{#2}%
\let\currentMPinstance\m_meta_saved_instance}
\installcommandhandler \??mpinstance {MPinstance} \??mpinstance
@@ -211,6 +211,7 @@
\def\currentMPformat {\currentMPinstance}
\defineMPinstance[metafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes]
+\defineMPinstance[minifun] [\s!format=minifun,\s!extensions=\v!yes,\s!initializations=\v!yes]
\defineMPinstance[extrafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes]
\defineMPinstance[lessfun] [\s!format=metafun]
\defineMPinstance[doublefun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes,\c!method=\s!double]
@@ -275,11 +276,13 @@
\endgroup}
\def\meta_process_graphic_start
- {\setbox\b_meta_graphic\hpack\bgroup}
+ {\pushMPboundingbox
+ \setbox\b_meta_graphic\hpack\bgroup}
\def\meta_process_graphic_stop
{\egroup
- \meta_place_graphic}
+ \meta_place_graphic
+ \popMPboundingbox}
\unexpanded\def\meta_process_graphic_instance#1%
{\edef\currentMPinstance{#1}%
@@ -365,12 +368,12 @@
\let\MPdrawingdata\empty
\unexpanded\def\resetMPdrawing
- {\global\let\MPdrawingdata\empty
+ {\glet\MPdrawingdata\empty
\global\MPdrawingdonefalse}
\unexpanded\def\pushMPdrawing
{\globalpushmacro\MPdrawingdata
- \global\let\MPdrawingdata\empty}
+ \glet\MPdrawingdata\empty}
\unexpanded\def\popMPdrawing
{\globalpopmacro\MPdrawingdata}
@@ -728,7 +731,7 @@
% \def\meta_start_use_graphic#1#2#3\stopuseMPgraphic
% %{\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}}
% %{\setxvalue{\??mpgraphic#1}{\noexpand\meta_handle_use_graphic{#1}{\normalunexpanded{#2}}{\normalunexpanded{#3}}}}
-% {\global\expandafter\gdef\csname\??mpgraphic#1\expandafter\endcsname\expandafter{\expandafter\meta_handle_use_graphic\expandafter{\normalexpanded{#1}}{#2}{#3}}}
+% {\expandafter\gdef\csname\??mpgraphic#1\expandafter\endcsname\expandafter{\expandafter\meta_handle_use_graphic\expandafter{\normalexpanded{#1}}{#2}{#3}}}
%
% cleaner:
@@ -785,11 +788,28 @@
\unexpanded\def\useMPgraphic
{\dodoublegroupempty\meta_use_graphic}
+% \def\meta_use_graphic#1#2%
+% {\meta_begin_graphic_group{#1}%
+% %\doifsomething{#2}{\setupMPvariables[\currentMPgraphicname][#2]}%
+% \doifsomething{#2}{\setupMPvariables[#1][#2]}%
+% \csname\??mpgraphic#1\endcsname\empty
+% \meta_end_graphic_group}
+
\def\meta_use_graphic#1#2%
{\meta_begin_graphic_group{#1}%
-% \doifsomething{#2}{\setupMPvariables[\currentMPgraphicname][#2]}%
- \doifsomething{#2}{\setupMPvariables[#1][#2]}%
- \csname\??mpgraphic#1\endcsname\empty
+ \ifcsname\??mpgraphic#1\endcsname
+ \edef\usedMPgraphicname{#1}%
+ \else\ifcsname\??mpgraphic\currentMPgraphicname\endcsname
+ \let\usedMPgraphicname\currentMPgraphicname
+ \else
+ \let\usedMPgraphicname\empty
+ \fi\fi
+ \ifx\usedMPgraphicname\empty
+ % message
+ \else
+ \doifsomething{#2}{\setupMPvariables[\usedMPgraphicname][#2]}%
+ \csname\??mpgraphic\usedMPgraphicname\endcsname
+ \fi
\meta_end_graphic_group}
\let\reuseMPgraphic \useMPgraphic % we can save a setup here if needed
@@ -861,19 +881,6 @@
{\meta_prepare_instance_variable{#1}%
\edef\overlaystamp{\overlaystamp:\MPvariable{#1}}}
-%D \macros
-%D {MPdatafile}
-%D
-%D We redefine a macro from \type {supp-mps.tex}:
-
-% This will change ...
-
-\def\MPdataMPYfile{\jobname-mpgraph.mpy}
-
-\startMPextensions
- def data_mpy_file = "\noexpand\MPdataMPYfile" enddef ;
-\stopMPextensions
-
\unexpanded\def\getMPdata {\clf_getMPdata}
\let\rawMPdata \clf_getMPdata
diff --git a/tex/context/base/mkiv/meta-nod.lua b/tex/context/base/mkiv/meta-nod.lua
new file mode 100644
index 000000000..422b4ee14
--- /dev/null
+++ b/tex/context/base/mkiv/meta-nod.lua
@@ -0,0 +1,81 @@
+if not modules then modules = { } end modules ['meta-nod'] = {
+ version = 1.001,
+ comment = "companion to meta-nod.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local tonumber = tonumber
+local P, R, Cs, lpegmatch = lpeg.P, lpeg.R, lpeg.Cs, lpeg.match
+
+local references = { }
+local trace = false
+local report = logs.reporter("metapost","nodes")
+
+local context = context
+local implement = interfaces.implement
+
+trackers.register("metapost.nodes", function(v) trace = v end)
+
+local word = R("AZ","az","__")^1
+
+local pattern = Cs (
+ (
+ word / function(s) return references[s] or s end
+ + P("{") / "["
+ + P("}") / "]"
+ + P(1)
+ )^1
+)
+
+implement {
+ name = "grph_nodes_initialize",
+ actions = function()
+ references = { }
+ end
+}
+
+implement {
+ name = "grph_nodes_reset",
+ actions = function()
+ references = { }
+ end
+}
+
+implement {
+ name = "grph_nodes_register",
+ arguments = { "string", "integer" },
+ actions = function(s,r)
+ if not tonumber(s) then
+ if trace then
+ report("register %i as %a",t,s)
+ end
+ references[s] = r
+ end
+ end
+}
+
+implement {
+ name = "grph_nodes_resolve",
+ arguments = "string",
+ actions = function(s)
+ local r = references[s]
+ if r then
+ if trace then
+ report("resolve %a to %i",s,r)
+ end
+ context(r)
+ return
+ end
+ local n = lpegmatch(pattern,s)
+ if s ~= n then
+ if trace then
+ report("resolve '%s' to %s",s,n)
+ end
+ context(n)
+ return
+ end
+ context(s)
+ end
+}
diff --git a/tex/context/base/mkiv/meta-nod.mkiv b/tex/context/base/mkiv/meta-nod.mkiv
index 5c7b3d503..9f966349c 100644
--- a/tex/context/base/mkiv/meta-nod.mkiv
+++ b/tex/context/base/mkiv/meta-nod.mkiv
@@ -11,6 +11,8 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+\registerctxluafile{meta-nod}{}
+
\unprotect
\defineMPinstance
@@ -105,6 +107,11 @@
\let\stopnodes\relax
+%D Hm, we started out simple but it now quickly becomes the usual mess of
+%D \TEX, \METAPOST\ and \LUA. Hard to understand.
+
+\newcount\c_meta_nodes_n
+
\unexpanded\def\startnodes
{\dosingleempty\meta_nodes_start}
@@ -116,10 +123,12 @@
\edef\p_meta_option{\metanodesparameter\c!option}%
\edef\p_meta_alternative{\metanodesparameter\c!alternative}%
\the\t_every_meta_nodes
+ \c_meta_nodes_n\zerocount
\t_meta_nodes\emptytoks
#2\removeunwantedspaces
% for alan, will be commented:
\writestatus{metanodes}{\detokenize\expandafter{\the\t_meta_nodes}}%
+ \clf_grph_nodes_initialize
\startMPcode
mfun_node_init(%
\the\dimexpr\metanodesparameter\c!dx\relax,%
@@ -129,11 +138,9 @@
\the\t_meta_nodes ;
mfun_node_flush ;
\stopMPcode
+ \clf_grph_nodes_reset
\egroup}
-% \unexpanded\def\grph_nodes_node[#1,#2]#3%
-% {\etoksapp\t_meta_nodes{mfun_node_make(\number#1,\number#2,"\metanodesparameter\c!command{#3}");}}
-
\unexpanded\def\grph_nodes_node
{\dodoubleempty\grph_nodes_node_two}
@@ -146,13 +153,20 @@
\setupcurrentmetanodes[#3]%
\fi
\edef\p_label{#4}%
+ \edef\p_reference{\metanodesparameter\c!reference}%
+ \ifx\p_reference\empty\else
+ \clf_grph_nodes_register{\p_reference}\c_meta_nodes_n\relax
+ \fi
\normalexpanded{\endgroup\noexpand\etoksapp\t_meta_nodes{%
mfun_node_make(\number#1,\number#2%
- \ifx\p_label\empty \else
+ \ifx\p_label\empty
+ ,""%
+ \else
,"\metanodesparameter\c!command{\p_label}"%
\fi
);%
- }}}
+ }}%
+ \advance\c_meta_nodes_n\plusone}
\appendtoks
\let\placenode\grph_nodes_node
@@ -199,8 +213,11 @@
\space
mfun_nodes_fromto\begincsname\??metanodesposition\metanodesparameter\c!position\endcsname(%
\metanodesparameter\c!offset,%
- \number#1,\number#2%
- \ifx\p_label\empty \else
+ % \number#1,\number#2%
+ \clf_grph_nodes_resolve{#1},\clf_grph_nodes_resolve{#2}%
+ \ifx\p_label\empty
+ ,""%
+ \else
,"\ifx\p_command\empty\p_label\else\p_command{\p_label}\fi"%
\fi
)%
diff --git a/tex/context/base/mkiv/meta-pdf.lua b/tex/context/base/mkiv/meta-pdf.lua
index 4a185cebd..5bcd161c0 100644
--- a/tex/context/base/mkiv/meta-pdf.lua
+++ b/tex/context/base/mkiv/meta-pdf.lua
@@ -6,6 +6,9 @@ if not modules then modules = { } end modules ['meta-pdf'] = {
license = "see context related readme files"
}
+-- This module is not used in practice but we keep it around for historic
+-- reasons.
+
-- 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.
@@ -35,20 +38,24 @@ local pdfgraycode = lpdf.graycode
local pdfspotcode = lpdf.spotcode
local pdftransparencycode = lpdf.transparencycode
local pdffinishtransparencycode = lpdf.finishtransparencycode
------ pdfpageliteral = nodes.pool.pdfpageliteral
metapost.mptopdf = metapost.mptopdf or { }
local mptopdf = metapost.mptopdf
mptopdf.nofconverted = 0
-local f_translate = formatters["1 0 0 0 1 %F %F cm"] -- no %s due to 1e-035 issues
-local f_concat = formatters["%F %F %F %F %F %F cm"] -- no %s due to 1e-035 issues
+local f_translate = formatters["1 0 0 0 1 %.6F %.6F cm"]
+local f_concat = formatters["%.6F %.6F %.6F %.6F %.6F %.6F cm"]
+
+directives.register("pdf.stripzeros",function()
+ f_translate = formatters["1 0 0 0 1 %.6N %.6N cm"]
+ f_concat = formatters["%.6N %.6N %.6N %.6N %.6N %.6N cm"]
+end)
local m_path, m_stack, m_texts, m_version, m_date, m_shortcuts = { }, { }, { }, 0, 0, false
local m_stack_close, m_stack_path, m_stack_concat = false, { }, nil
-local extra_path_code, ignore_path = nil, false
+local extra_path_data, ignore_path = nil, false
local specials = { }
local function resetpath()
@@ -57,28 +64,21 @@ end
local function resetall()
m_path, m_stack, m_texts, m_version, m_shortcuts = { }, { }, { }, 0, false
- extra_path_code, ignore_path = nil, false
+ extra_path_data, ignore_path = nil, false
specials = { }
resetpath()
end
resetall()
--- -- this does not work as expected (displacement of text) beware, needs another
--- -- comment hack
---
--- local function pdfcode(str)
--- context(pdfpageliteral(str))
--- end
-
local pdfcode = context.pdfliteral
local function mpscode(str)
if ignore_path then
pdfcode("h W n")
- if extra_path_code then
- pdfcode(extra_path_code)
- extra_path_code = nil
+ if extra_path_data then
+ pdfcode(extra_path_data)
+ extra_path_data = nil
end
ignore_path = false
else
@@ -99,16 +99,28 @@ local function flushpath(cmd)
if #m_stack_path > 0 then
local path = { }
if m_stack_concat then
- local sx, sy = m_stack_concat[1], m_stack_concat[4]
- local rx, ry = m_stack_concat[2], m_stack_concat[3]
- local tx, ty = m_stack_concat[5], m_stack_concat[6]
+ local sx = m_stack_concat[1]
+ local sy = m_stack_concat[4]
+ local rx = m_stack_concat[2]
+ local ry = m_stack_concat[3]
+ local tx = m_stack_concat[5]
+ local ty = m_stack_concat[6]
local d = (sx*sy) - (rx*ry)
for k=1,#m_stack_path do
- local v = m_stack_path[k]
- local px, py = v[1], v[2] ; v[1], v[2] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[1],v[2])
+ local v = m_stack_path[k]
+ local px = v[1]
+ local py = v[2]
+ v[1] = (sy*(px-tx)-ry*(py-ty))/d
+ v[2] = (sx*(py-ty)-rx*(px-tx))/d
if #v == 7 then
- local px, py = v[3], v[4] ; v[3], v[4] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[3],v[4])
- local px, py = v[5], v[6] ; v[5], v[6] = (sy*(px-tx)-ry*(py-ty))/d, (sx*(py-ty)-rx*(px-tx))/d -- mpconcat(v[5],v[6])
+ px = v[3]
+ py = v[4]
+ v[3] = (sy*(px-tx)-ry*(py-ty))/d
+ v[4] = (sx*(py-ty)-rx*(px-tx))/d
+ px = v[5]
+ py = v[6]
+ v[5] = (sy*(px-tx)-ry*(py-ty))/d
+ v[6] = (sx*(py-ty)-rx*(px-tx))/d
end
path[k] = concat(v," ")
end
@@ -161,7 +173,8 @@ function mps.lineto(x,y)
end
function mps.rlineto(x,y)
- local dx, dy = 0, 0
+ local dx = 0
+ local dy = 0
local topofstack = #m_stack_path
if topofstack > 0 then
local msp = m_stack_path[topofstack]
@@ -238,7 +251,8 @@ function mps.clip()
end
function mps.textext(font, scale, str) -- old parser
- local dx, dy = 0, 0
+ local dx = 0
+ local dy = 0
if #m_stack_path > 0 then
dx, dy = m_stack_path[1][1], m_stack_path[1][2]
end
@@ -279,7 +293,7 @@ local function linearshade(colorspace,domain,ca,cb,coordinates)
nofshades = nofshades + 1
local name = formatters["MpsSh%s"](nofshades)
lpdf.linearshade(name,domain,ca,cb,1,colorspace,coordinates)
- extra_path_code, ignore_path = formatters["/%s sh Q"](name), true
+ extra_path_data, ignore_path = formatters["/%s sh Q"](name), true
pdfcode("q /Pattern cs")
end
@@ -288,7 +302,7 @@ local function circularshade(colorspace,domain,ca,cb,coordinates)
nofshades = nofshades + 1
local name = formatters["MpsSh%s"](nofshades)
lpdf.circularshade(name,domain,ca,cb,1,colorspace,coordinates)
- extra_path_code, ignore_path = formatters["/%s sh Q"](name), true
+ extra_path_data, ignore_path = formatters["/%s sh Q"](name), true
pdfcode("q /Pattern cs")
end
@@ -333,9 +347,12 @@ handlers[50] = function() report_mptopdf("skipping special %s",50) end
--end of not supported
function mps.setrgbcolor(r,g,b) -- extra check
- r, g, b = tonumber(r), tonumber(g), tonumber(b) -- needed when we use lpeg
+ r = tonumber(r) -- needed when we use lpeg
+ g = tonumber(g) -- needed when we use lpeg
+ b = tonumber(b) -- needed when we use lpeg
if r == 0.0123 and g < 0.1 then
- g, b = round(g*10000), round(b*10000)
+ g = round(g*10000)
+ b = round(b*10000)
local s = specials[b]
local h = round(s[#s])
local handler = handlers[h]
@@ -345,7 +362,8 @@ function mps.setrgbcolor(r,g,b) -- extra check
report_mptopdf("unknown special handler %s (1)",h)
end
elseif r == 0.123 and g < 0.1 then
- g, b = round(g*1000), round(b*1000)
+ g = round(g*1000)
+ b = round(b*1000)
local s = specials[b]
local h = round(s[#s])
local handler = handlers[h]
diff --git a/tex/context/base/mkiv/meta-pdh.mkiv b/tex/context/base/mkiv/meta-pdh.mkiv
index f9eff73ca..e4ac92fb4 100644
--- a/tex/context/base/mkiv/meta-pdh.mkiv
+++ b/tex/context/base/mkiv/meta-pdh.mkiv
@@ -92,15 +92,15 @@
{\ifx\objectoffset\undefined\zeropoint\else\objectoffset\fi}
\def\resetMPvariables#1#2#3%
- {\global\let\MPwidth \!!zeropoint
- \global\let\MPheight\!!zeropoint
- \global\let\MPllx \!!zerocount
- \global\let\MPlly \!!zerocount
- \global\let\MPurx \!!zerocount
- \global\let\MPury \!!zerocount
- \xdef\MPxscale {#2}\ifx\MPxscale\empty\let\MPxscale\!!plusone\fi
- \xdef\MPyscale {#3}\ifx\MPyscale\empty\let\MPyscale\!!plusone\fi
- \xdef\MPfilename {#1}}
+ {\glet\MPwidth \!!zeropoint
+ \glet\MPheight \!!zeropoint
+ \glet\MPllx \!!zerocount
+ \glet\MPlly \!!zerocount
+ \glet\MPurx \!!zerocount
+ \glet\MPury \!!zerocount
+ \xdef\MPxscale {#2}\ifx\MPxscale\empty\let\MPxscale\!!plusone\fi
+ \xdef\MPyscale {#3}\ifx\MPyscale\empty\let\MPyscale\!!plusone\fi
+ \xdef\MPfilename {#1}}
%D The main macro:
@@ -164,7 +164,7 @@
\else
\getMPPDFobject
\fi
- \global\let\currentPDFresources\empty
+ \glet\currentPDFresources\empty
\else
\box#1%
\fi}
@@ -250,12 +250,12 @@
%D Some day we may consider collecting local resources.
\appendtoks
- \global\let\currentPDFresources\empty % kind of redundant
+ \glet\currentPDFresources\empty % kind of redundant
\to \MPstartresources
% \appendtoks
% \collectPDFresources
-% \global\let\currentPDFresources\collectedPDFresources
+% \glet\currentPDFresources\collectedPDFresources
% \to \MPstopresources
\appendtoksonce
diff --git a/tex/context/base/mkiv/meta-tex.lua b/tex/context/base/mkiv/meta-tex.lua
index fdf118424..c2f72bcf3 100644
--- a/tex/context/base/mkiv/meta-tex.lua
+++ b/tex/context/base/mkiv/meta-tex.lua
@@ -126,11 +126,7 @@ do
arguments = "2 strings",
}
- if LUAVERSION < 5.2 then
- utilities.strings.formatters.add(formatters,"texexp", [[texexp(...)]], "local texexp = metapost.texexp")
- else
- utilities.strings.formatters.add(formatters,"texexp", [[texexp(...)]], { texexp = metapost.texexp })
- end
+ utilities.strings.formatters.add(formatters,"texexp", [[texexp(...)]], { texexp = metapost.texexp })
local f_textext = formatters[ [[textext("%s")]] ]
local f_mthtext = formatters[ [[textext("\mathematics{%s}")]] ]
diff --git a/tex/context/base/mkiv/metatex.tex b/tex/context/base/mkiv/metatex.tex
deleted file mode 100644
index 7c8a7ff01..000000000
--- a/tex/context/base/mkiv/metatex.tex
+++ /dev/null
@@ -1,30 +0,0 @@
-%D \module
-%D [ file=metatex,
-%D version=2008.10.10,
-%D title=\METATEX,
-%D subtitle=\METATEX\ Format Generation,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-%D We can experiment here with runtime loading, i.e. no longer
-%D use a format. However, we still need a stub then but it could
-%D as well be luatools (mtxrun) itself then.
-
-%D This format is just a minimal layer on top of the \LUATEX\
-%D engine and will not provide high level functionality. It can
-%D be used as basis for dedicated (specialized) macro packages.
-%D
-%D A format is generated with the command;
-%D
-%D \starttyping
-%D mtxrun --script metatex --make
-%D \stoptyping
-%D
-%D For the moment this is a placeholder. Maybe some day ... the old
-%D file history/metatex/metatex.tex so I can pick up from there if
-%D needed.
diff --git a/tex/context/base/mkiv/mlib-ctx.lua b/tex/context/base/mkiv/mlib-ctx.lua
index c568b92a3..89f2fa0ee 100644
--- a/tex/context/base/mkiv/mlib-ctx.lua
+++ b/tex/context/base/mkiv/mlib-ctx.lua
@@ -11,46 +11,29 @@ local format, concat = string.format, table.concat
local settings_to_hash = utilities.parsers.settings_to_hash
local formatters = string.formatters
-local report_metapost = logs.reporter("metapost")
+local report_metapost = logs.reporter ("metapost")
+local status_metapost = logs.messenger("metapost")
-local starttiming = statistics.starttiming
-local stoptiming = statistics.stoptiming
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
-local mplib = mplib
+local trace_graphic = false
-metapost = metapost or { }
-local metapost = metapost
-local context = context
+trackers.register("metapost.graphics",
+ function(v) trace_graphic = v end
+);
-local setters = tokens.setters
-local setmacro = setters.macro
-local implement = interfaces.implement
+local mplib = mplib
-local v_no = interfaces.variables.no
+metapost = metapost or { }
+local metapost = metapost
+local context = context
-metapost.defaultformat = "metafun"
-metapost.defaultinstance = "metafun"
-metapost.defaultmethod = "default"
+local setters = tokens.setters
+local setmacro = setters.macro
+local implement = interfaces.implement
-local function setmpsformat(specification)
- local instance = specification.instance
- local format = specification.format
- local method = specification.method
- if not instance or instance == "" then
- instance = metapost.defaultinstance
- specification.instance = instance
- end
- if not format or format == "" then
- format = metapost.defaultformat
- specification.format = format
- end
- if not method or method == "" then
- method = metapost.defaultmethod
- specification.method = method
- end
- specification.mpx = metapost.format(instance,format,method)
- return specification
-end
+local v_no = interfaces.variables.no
local extensiondata = metapost.extensiondata or storage.allocate { }
metapost.extensiondata = extensiondata
@@ -96,9 +79,6 @@ implement {
arguments = "string"
}
-local report_metapost = logs.reporter ("metapost")
-local status_metapost = logs.messenger("metapost")
-
local patterns = {
"meta-imp-%s.mkiv",
"meta-imp-%s.tex",
@@ -192,7 +172,9 @@ implement {
-- or just move the scanners to pps
function metapost.graphic(specification)
- metapost.graphic_base_pass(setmpsformat(specification))
+ metapost.pushformat(specification)
+ metapost.graphic_base_pass(specification)
+ metapost.popformat()
end
function metapost.startgraphic(t)
@@ -208,9 +190,6 @@ function metapost.startgraphic(t)
if not t.method then
t.method = metapost.defaultmethod
end
- if not t.definitions then
- t.definitions = ""
- end
t.data = { }
return t
end
@@ -218,8 +197,10 @@ end
function metapost.stopgraphic(t)
if t then
t.data = concat(t.data or { },"\n")
+ if trace_graphic then
+ report_metapost("\n"..t.data.."\n")
+ end
metapost.graphic(t)
- t.data = ""
end
end
@@ -265,8 +246,7 @@ implement {
}
function metapost.getclippath(specification) -- why not a special instance for this
- setmpsformat(specification)
- local mpx = specification.mpx
+ local mpx = metapost.pushformat(specification)
local data = specification.data or ""
if mpx and data ~= "" then
starttiming(metapost)
@@ -285,7 +265,10 @@ function metapost.getclippath(specification) -- why not a special instance for t
result = metapost.filterclippath(result)
end
stoptiming(metapost)
+ metapost.pushformat()
return result
+ else
+ metapost.pushformat()
end
end
@@ -337,23 +320,17 @@ implement {
}
}
-statistics.register("metapost processing time", function()
+statistics.register("metapost", function()
local n = metapost.n
if n and n > 0 then
- local nofconverted = metapost.makempy.nofconverted
local elapsedtime = statistics.elapsedtime
- local elapsed = statistics.elapsed
- local instances, memory = metapost.getstatistics(true)
- local str = format("%s seconds, loading: %s, execution: %s, n: %s, average: %s, instances: %i, memory: %0.3f M",
+ local elapsed = statistics.elapsed
+ local instances,
+ memory = metapost.getstatistics(true)
+ return format("%s seconds, loading: %s, execution: %s, n: %s, average: %s, instances: %i, luacalls: %i, memory: %0.3f M",
elapsedtime(metapost), elapsedtime(mplib), elapsedtime(metapost.exectime), n,
elapsedtime((elapsed(metapost) + elapsed(mplib) + elapsed(metapost.exectime)) / n),
- instances, memory/(1024*1024))
- if nofconverted > 0 then
- return format("%s, external: %s (%s calls)",
- str, elapsedtime(metapost.makempy), nofconverted)
- else
- return str
- end
+ instances, metapost.nofscriptruns(),memory/(1024*1024))
else
return nil
end
diff --git a/tex/context/base/mkiv/mlib-int.lua b/tex/context/base/mkiv/mlib-int.lua
index bd3ba213f..63e7278da 100644
--- a/tex/context/base/mkiv/mlib-int.lua
+++ b/tex/context/base/mkiv/mlib-int.lua
@@ -7,11 +7,14 @@ if not modules then modules = { } end modules ['mlib-int'] = {
}
local factor = number.dimenfactors.bp
-local mpprint = mp.print
------ mpboolean = mp.boolean
------ mpquoted = mp.quoted
+----- mpprint = mp.print
+local mpnumeric = mp.numeric
+local mpboolean = mp.boolean
+local mpstring = mp.string
+local mpquoted = mp.quoted
local getdimen = tex.getdimen
local getcount = tex.getcount
+local getmacro = tokens.getters.macro
local get = tex.get
local mpcolor = attributes.colors.mpcolor
local emwidths = fonts.hashes.emwidths
@@ -19,90 +22,90 @@ local exheights = fonts.hashes.exheights
local mpgetdimen = mp.getdimen
-function mp.PaperHeight () mpprint(getdimen("paperheight") *factor) end
-function mp.PaperWidth () mpprint(getdimen("paperwidth") *factor) end
-function mp.PrintPaperHeight () mpprint(getdimen("printpaperheight") *factor) end
-function mp.PrintPaperWidth () mpprint(getdimen("printpaperwidth") *factor) end
-function mp.TopSpace () mpprint(getdimen("topspace") *factor) end
-function mp.BottomSpace () mpprint(getdimen("bottomspace") *factor) end
-function mp.BackSpace () mpprint(getdimen("backspace") *factor) end
-function mp.CutSpace () mpprint(getdimen("cutspace") *factor) end
-function mp.MakeupHeight () mpprint(getdimen("makeupheight") *factor) end
-function mp.MakeupWidth () mpprint(getdimen("makeupwidth") *factor) end
-function mp.TopHeight () mpprint(getdimen("topheight") *factor) end
-function mp.TopDistance () mpprint(getdimen("topdistance") *factor) end
-function mp.HeaderHeight () mpprint(getdimen("headerheight") *factor) end
-function mp.HeaderDistance () mpprint(getdimen("headerdistance") *factor) end
-function mp.TextHeight () mpprint(getdimen("textheight") *factor) end
-function mp.FooterDistance () mpprint(getdimen("footerdistance") *factor) end
-function mp.FooterHeight () mpprint(getdimen("footerheight") *factor) end
-function mp.BottomDistance () mpprint(getdimen("bottomdistance") *factor) end
-function mp.BottomHeight () mpprint(getdimen("bottomheight") *factor) end
-function mp.LeftEdgeWidth () mpprint(getdimen("leftedgewidth") *factor) end
-function mp.LeftEdgeDistance () mpprint(getdimen("leftedgedistance") *factor) end
-function mp.LeftMarginWidth () mpprint(getdimen("leftmarginwidth") *factor) end
-function mp.LeftMarginDistance () mpprint(getdimen("leftmargindistance") *factor) end
-function mp.TextWidth () mpprint(getdimen("textwidth") *factor) end
-function mp.RightMarginDistance () mpprint(getdimen("rightmargindistance") *factor) end
-function mp.RightMarginWidth () mpprint(getdimen("rightmarginwidth") *factor) end
-function mp.RightEdgeDistance () mpprint(getdimen("rightedgedistance") *factor) end
-function mp.RightEdgeWidth () mpprint(getdimen("rightedgewidth") *factor) end
-function mp.InnerMarginDistance () mpprint(getdimen("innermargindistance") *factor) end
-function mp.InnerMarginWidth () mpprint(getdimen("innermarginwidth") *factor) end
-function mp.OuterMarginDistance () mpprint(getdimen("outermargindistance") *factor) end
-function mp.OuterMarginWidth () mpprint(getdimen("outermarginwidth") *factor) end
-function mp.InnerEdgeDistance () mpprint(getdimen("inneredgedistance") *factor) end
-function mp.InnerEdgeWidth () mpprint(getdimen("inneredgewidth") *factor) end
-function mp.OuterEdgeDistance () mpprint(getdimen("outeredgedistance") *factor) end
-function mp.OuterEdgeWidth () mpprint(getdimen("outeredgewidth") *factor) end
-function mp.PageOffset () mpprint(getdimen("pagebackgroundoffset")*factor) end
-function mp.PageDepth () mpprint(getdimen("pagebackgrounddepth") *factor) end
-function mp.LayoutColumns () mpprint(getcount("layoutcolumns")) end
-function mp.LayoutColumnDistance() mpprint(getdimen("layoutcolumndistance")*factor) end
-function mp.LayoutColumnWidth () mpprint(getdimen("layoutcolumnwidth") *factor) end
-function mp.SpineWidth () mpprint(getdimen("spinewidth") *factor) end
-function mp.PaperBleed () mpprint(getdimen("paperbleed") *factor) end
-
-function mp.RealPageNumber () mpprint(getcount("realpageno")) end
-function mp.LastPageNumber () mpprint(getcount("lastpageno")) end
-
-function mp.PageNumber () mpprint(getcount("pageno")) end
-function mp.NOfPages () mpprint(getcount("lastpageno")) end
-
-function mp.SubPageNumber () mpprint(getcount("subpageno")) end
-function mp.NOfSubPages () mpprint(getcount("lastsubpageno")) end
-
-function mp.CurrentColumn () mpprint(getcount("mofcolumns")) end
-function mp.NOfColumns () mpprint(getcount("nofcolumns")) end
-
-function mp.BaseLineSkip () mpprint(get ("baselineskip",true) *factor) end
-function mp.LineHeight () mpprint(getdimen("lineheight") *factor) end
-function mp.BodyFontSize () mpprint(getdimen("bodyfontsize") *factor) end
-
-function mp.TopSkip () mpprint(get ("topskip",true) *factor) end
-function mp.StrutHeight () mpprint(getdimen("strutht") *factor) end
-function mp.StrutDepth () mpprint(getdimen("strutdp") *factor) end
-
-function mp.PageNumber () mpprint(getcount("pageno")) end
-function mp.RealPageNumber () mpprint(getcount("realpageno")) end
-function mp.NOfPages () mpprint(getcount("lastpageno")) end
-
-function mp.CurrentWidth () mpprint(get ("hsize") *factor) end
-function mp.CurrentHeight () mpprint(get ("vsize") *factor) end
-
-function mp.EmWidth () mpprint(emwidths [false]*factor) end
-function mp.ExHeight () mpprint(exheights[false]*factor) end
+function mp.PaperHeight () mpnumeric(getdimen("paperheight") *factor) end
+function mp.PaperWidth () mpnumeric(getdimen("paperwidth") *factor) end
+function mp.PrintPaperHeight () mpnumeric(getdimen("printpaperheight") *factor) end
+function mp.PrintPaperWidth () mpnumeric(getdimen("printpaperwidth") *factor) end
+function mp.TopSpace () mpnumeric(getdimen("topspace") *factor) end
+function mp.BottomSpace () mpnumeric(getdimen("bottomspace") *factor) end
+function mp.BackSpace () mpnumeric(getdimen("backspace") *factor) end
+function mp.CutSpace () mpnumeric(getdimen("cutspace") *factor) end
+function mp.MakeupHeight () mpnumeric(getdimen("makeupheight") *factor) end
+function mp.MakeupWidth () mpnumeric(getdimen("makeupwidth") *factor) end
+function mp.TopHeight () mpnumeric(getdimen("topheight") *factor) end
+function mp.TopDistance () mpnumeric(getdimen("topdistance") *factor) end
+function mp.HeaderHeight () mpnumeric(getdimen("headerheight") *factor) end
+function mp.HeaderDistance () mpnumeric(getdimen("headerdistance") *factor) end
+function mp.TextHeight () mpnumeric(getdimen("textheight") *factor) end
+function mp.FooterDistance () mpnumeric(getdimen("footerdistance") *factor) end
+function mp.FooterHeight () mpnumeric(getdimen("footerheight") *factor) end
+function mp.BottomDistance () mpnumeric(getdimen("bottomdistance") *factor) end
+function mp.BottomHeight () mpnumeric(getdimen("bottomheight") *factor) end
+function mp.LeftEdgeWidth () mpnumeric(getdimen("leftedgewidth") *factor) end
+function mp.LeftEdgeDistance () mpnumeric(getdimen("leftedgedistance") *factor) end
+function mp.LeftMarginWidth () mpnumeric(getdimen("leftmarginwidth") *factor) end
+function mp.LeftMarginDistance () mpnumeric(getdimen("leftmargindistance") *factor) end
+function mp.TextWidth () mpnumeric(getdimen("textwidth") *factor) end
+function mp.RightMarginDistance () mpnumeric(getdimen("rightmargindistance") *factor) end
+function mp.RightMarginWidth () mpnumeric(getdimen("rightmarginwidth") *factor) end
+function mp.RightEdgeDistance () mpnumeric(getdimen("rightedgedistance") *factor) end
+function mp.RightEdgeWidth () mpnumeric(getdimen("rightedgewidth") *factor) end
+function mp.InnerMarginDistance () mpnumeric(getdimen("innermargindistance") *factor) end
+function mp.InnerMarginWidth () mpnumeric(getdimen("innermarginwidth") *factor) end
+function mp.OuterMarginDistance () mpnumeric(getdimen("outermargindistance") *factor) end
+function mp.OuterMarginWidth () mpnumeric(getdimen("outermarginwidth") *factor) end
+function mp.InnerEdgeDistance () mpnumeric(getdimen("inneredgedistance") *factor) end
+function mp.InnerEdgeWidth () mpnumeric(getdimen("inneredgewidth") *factor) end
+function mp.OuterEdgeDistance () mpnumeric(getdimen("outeredgedistance") *factor) end
+function mp.OuterEdgeWidth () mpnumeric(getdimen("outeredgewidth") *factor) end
+function mp.PageOffset () mpnumeric(getdimen("pagebackgroundoffset")*factor) end
+function mp.PageDepth () mpnumeric(getdimen("pagebackgrounddepth") *factor) end
+function mp.LayoutColumns () mpnumeric(getcount("layoutcolumns")) end
+function mp.LayoutColumnDistance() mpnumeric(getdimen("layoutcolumndistance")*factor) end
+function mp.LayoutColumnWidth () mpnumeric(getdimen("layoutcolumnwidth") *factor) end
+function mp.SpineWidth () mpnumeric(getdimen("spinewidth") *factor) end
+function mp.PaperBleed () mpnumeric(getdimen("paperbleed") *factor) end
+
+function mp.RealPageNumber () mpnumeric(getcount("realpageno")) end
+function mp.LastPageNumber () mpnumeric(getcount("lastpageno")) end
+
+function mp.PageNumber () mpnumeric(getcount("pageno")) end
+function mp.NOfPages () mpnumeric(getcount("lastpageno")) end
+
+function mp.SubPageNumber () mpnumeric(getcount("subpageno")) end
+function mp.NOfSubPages () mpnumeric(getcount("lastsubpageno")) end
+
+function mp.CurrentColumn () mpnumeric(getcount("mofcolumns")) end
+function mp.NOfColumns () mpnumeric(getcount("nofcolumns")) end
+
+function mp.BaseLineSkip () mpnumeric(get ("baselineskip",true) *factor) end
+function mp.LineHeight () mpnumeric(getdimen("lineheight") *factor) end
+function mp.BodyFontSize () mpnumeric(getdimen("bodyfontsize") *factor) end
+
+function mp.TopSkip () mpnumeric(get ("topskip",true) *factor) end
+function mp.StrutHeight () mpnumeric(getdimen("strutht") *factor) end
+function mp.StrutDepth () mpnumeric(getdimen("strutdp") *factor) end
+
+function mp.PageNumber () mpnumeric(getcount("pageno")) end
+function mp.RealPageNumber () mpnumeric(getcount("realpageno")) end
+function mp.NOfPages () mpnumeric(getcount("lastpageno")) end
+
+function mp.CurrentWidth () mpnumeric(get ("hsize") *factor) end
+function mp.CurrentHeight () mpnumeric(get ("vsize") *factor) end
+
+function mp.EmWidth () mpnumeric(emwidths [false]*factor) end
+function mp.ExHeight () mpnumeric(exheights[false]*factor) end
mp.HSize = mp.CurrentWidth
mp.VSize = mp.CurrentHeight
mp.LastPageNumber = mp.NOfPages
-function mp.PageFraction ()
+function mp.PageFraction()
local lastpage = getcount("lastpageno")
if lastpage > 1 then
- mpprint((getcount("realpageno")-1)/(lastpage-1))
+ mpnumeric((getcount("realpageno")-1)/(lastpage-1))
else
- mpprint(1)
+ mpnumeric(1)
end
end
@@ -112,30 +115,22 @@ local on_right = structures.pages.on_right
local is_odd = structures.pages.is_odd
local in_body = structures.pages.in_body
-mp.OnRightPage = function() mpprint(on_right()) end -- needs checking
-mp.OnOddPage = function() mpprint(is_odd ()) end -- needs checking
-mp.InPageBody = function() mpprint(in_body ()) end -- needs checking
+mp.OnRightPage = function() mpboolean(on_right()) end -- needs checking
+mp.OnOddPage = function() mpboolean(is_odd ()) end -- needs checking
+mp.InPageBody = function() mpboolean(in_body ()) end -- needs checking
-- mp.CurrentLayout : \currentlayout
-function mp.OverlayWidth () mpprint(getdimen("d_overlay_width") *factor) end
-function mp.OverlayHeight () mpprint(getdimen("d_overlay_height") *factor) end
-function mp.OverlayDepth () mpprint(getdimen("d_overlay_depth") *factor) end
-function mp.OverlayLineWidth () mpprint(getdimen("d_overlay_linewidth")*factor) end
-function mp.OverlayOffset () mpprint(getdimen("d_overlay_offset") *factor) end
+function mp.OverlayWidth () mpnumeric(getdimen("d_overlay_width") * factor) end
+function mp.OverlayHeight () mpnumeric(getdimen("d_overlay_height") * factor) end
+function mp.OverlayDepth () mpnumeric(getdimen("d_overlay_depth") * factor) end
+function mp.OverlayLineWidth() mpnumeric(getdimen("d_overlay_linewidth") * factor) end
+function mp.OverlayOffset () mpnumeric(getdimen("d_overlay_offset") * factor) end
+function mp.OverlayRegion () mpstring(getmacro("m_overlay_region")) end
-function mp.defaultcolormodel()
+function mp.mf_default_color_model()
local colormethod = getcount("MPcolormethod")
- -- if colormethod == 0 then
- -- return 1
- -- elseif colormethod == 1 then
- -- return 1
- -- elseif colormethod == 2 then
- -- return 3
- -- else
- -- return 3
- -- end
- return (colormethod == 0 or colormethod == 1) and 1 or 3
+ return mpnumeric((colormethod == 0 or colormethod == 1) and 1 or 3)
end
-- not much difference (10000 calls in a graphic neither as expansion seems to win
diff --git a/tex/context/base/mkiv/mlib-lua.lua b/tex/context/base/mkiv/mlib-lua.lua
index 19e731b85..d7c2a0fc3 100644
--- a/tex/context/base/mkiv/mlib-lua.lua
+++ b/tex/context/base/mkiv/mlib-lua.lua
@@ -10,11 +10,11 @@ if not modules then modules = { } end modules ['mlib-lua'] = {
-- maybe we need mplib.model, but how with instances
-local type, tostring, select, loadstring = type, tostring, select, loadstring
+local type, tostring, tonumber, select, loadstring = type, tostring, tonumber, select, loadstring
local find, match, gsub, gmatch = string.find, string.match, string.gsub, string.gmatch
+local concat, insert, remove = table.concat, table.insert, table.remove
local formatters = string.formatters
-local concat = table.concat
local lpegmatch = lpeg.match
local lpegpatterns = lpeg.patterns
@@ -26,105 +26,18 @@ local report_message = logs.reporter("metapost")
local trace_luarun = false trackers.register("metapost.lua",function(v) trace_luarun = v end)
local trace_enabled = true
-local be_tolerant = true directives.register("metapost.lua.tolerant",function(v) be_tolerant = v end)
+local be_tolerant = true directives.register("metapost.lua.tolerant", function(v) be_tolerant = v end)
-mp = mp or { } -- system namespace
-MP = MP or { } -- user namespace
+local get, set, aux = { }, { }, { }
-local buffer, n, max = { }, 0, 10 -- we reuse upto max
-
-function mp._f_()
- if trace_enabled and trace_luarun then
- local result = concat(buffer," ",1,n)
- if n > max then
- buffer = { }
- end
- n = 0
- report_luarun("data: %s",result)
- return result
- else
- if n == 0 then
- return ""
- end
- local result
- if n == 1 then
- result = buffer[1]
- else
- result = concat(buffer," ",1,n)
- end
- if n > max then
- buffer = { }
- end
- n = 0
- return result
- end
-end
-
-local f_code = formatters["%s return mp._f_()"]
-
-local f_numeric = formatters["%.16f"]
-local f_integer = formatters["%i"]
-local f_pair = formatters["(%.16f,%.16f)"]
-local f_triplet = formatters["(%.16f,%.16f,%.16f)"]
-local f_quadruple = formatters["(%.16f,%.16f,%.16f,%.16f)"]
-
-local function mpprint(...) -- we can optimize for n=1
- for i=1,select("#",...) do
- local value = select(i,...)
- if value ~= nil then
- n = n + 1
- local t = type(value)
- if t == "number" then
- buffer[n] = f_numeric(value)
- elseif t == "string" then
- buffer[n] = value
- elseif t == "table" then
- buffer[n] = "(" .. concat(value,",") .. ")"
- else -- boolean or whatever
- buffer[n] = tostring(value)
- end
- end
- end
-end
-
-local r = P('%') / "percent"
- + P('"') / "dquote"
- + P('\n') / "crlf"
- -- + P(' ') / "space"
-local a = Cc("&")
-local q = Cc('"')
-local p = Cs(q * (r * a)^-1 * (a * r * (P(-1) + a) + P(1))^0 * q)
-
-local function mpvprint(...) -- variable print
- for i=1,select("#",...) do
- local value = select(i,...)
- if value ~= nil then
- n = n + 1
- local t = type(value)
- if t == "number" then
- buffer[n] = f_numeric(value)
- elseif t == "string" then
- buffer[n] = lpegmatch(p,value)
- elseif t == "table" then
- local m = #t
- if m == 2 then
- buffer[n] = f_pair(unpack(t))
- elseif m == 3 then
- buffer[n] = f_triplet(unpack(t))
- elseif m == 4 then
- buffer[n] = f_quadruple(unpack(t))
- else -- error
- buffer[n] = ""
- end
- else -- boolean or whatever
- buffer[n] = tostring(value)
- end
- end
- end
-end
+mp = mp or { -- system namespace
+ set = set,
+ get = get,
+ aux = aux,
+}
-mp.print = mpprint
-mp.vprint = mpvprint
+MP = MP or { -- user namespace
+}
-- We had this:
--
@@ -139,150 +52,540 @@ mp.vprint = mpvprint
-- lua.mp("somedefdname","foo")
table.setmetatablecall(mp,function(t,k,...) return t[k](...) end)
+table.setmetatablecall(MP,function(t,k,...) return t[k](...) end)
-function mp.boolean(b)
- n = n + 1
- buffer[n] = b and "true" or "false"
-end
+do
-function mp.numeric(f)
- n = n + 1
- buffer[n] = f and f_numeric(f) or "0"
-end
+ local currentmpx = nil
+ local stack = { }
-function mp.integer(i)
- n = n + 1
- -- buffer[n] = i and f_integer(i) or "0"
- buffer[n] = i or "0"
-end
+ local get_numeric = mplib.get_numeric
+ local get_string = mplib.get_string
+ local get_boolean = mplib.get_boolean
+ local get_path = mplib.get_path
+ local set_path = mplib.set_path
+
+ get.numeric = function(s) return get_numeric(currentmpx,s) end
+ get.string = function(s) return get_string (currentmpx,s) end
+ get.boolean = function(s) return get_boolean(currentmpx,s) end
+ get.path = function(s) return get_path (currentmpx,s) end
+ get.number = function(s) return get_numeric(currentmpx,s) end
-function mp.pair(x,y)
- n = n + 1
- if type(x) == "table" then
- buffer[n] = f_pair(x[1],x[2])
- else
- buffer[n] = f_pair(x,y)
+ set.path = function(s,t) return set_path(currentmpx,s,t) end -- not working yet
+
+ function metapost.pushscriptrunner(mpx)
+ insert(stack,mpx)
+ currentmpx = mpx
end
-end
-function mp.triplet(x,y,z)
- n = n + 1
- if type(x) == "table" then
- buffer[n] = f_triplet(x[1],x[2],x[3])
- else
- buffer[n] = f_triplet(x,y,z)
+ function metapost.popscriptrunner()
+ currentmpx = remove(stack,mpx)
end
+
end
-function mp.quadruple(w,x,y,z)
- n = n + 1
- if type(w) == "table" then
- buffer[n] = f_quadruple(w[1],w[2],w[3],w[4])
- else
- buffer[n] = f_quadruple(w,x,y,z)
+do
+
+ local buffer = { }
+ local n = 0
+ local max = 20 -- we reuse upto max
+ local nesting = 0
+ local runs = 0
+
+ local function _f_()
+ if trace_enabled and trace_luarun then
+ local result = concat(buffer," ",1,n)
+ if n > max then
+ buffer = { }
+ end
+ n = 0
+ report_luarun("%i: data: %s",nesting,result)
+ return result
+ else
+ if n == 0 then
+ return ""
+ end
+ local result
+ if n == 1 then
+ result = buffer[1]
+ else
+ result = concat(buffer," ",1,n)
+ end
+ if n > max then
+ buffer = { }
+ end
+ n = 0
+ return result
+ end
+ end
+
+ mp._f_ = _f_ -- convenient to have it in a top module
+ aux.flush = _f_
+
+ ----- f_code = formatters["%s return mp._f_()"]
+
+ local f_integer = formatters["%i"]
+
+ local f_numeric = formatters["%n"] -- maybe %N
+ local f_pair = formatters["(%n,%n)"]
+ local f_ctrl = formatters["(%n,%n) .. controls (%n,%n) and (%n,%n)"]
+ local f_triplet = formatters["(%n,%n,%n)"]
+ local f_quadruple = formatters["(%n,%n,%n,%n)"]
+
+ local f_points = formatters["%p"]
+ local f_pair_pt = formatters["(%p,%p)"]
+ local f_ctrl_pt = formatters["(%p,%p) .. controls (%p,%p) and (%p,%p)"]
+ local f_triplet_pt = formatters["(%p,%p,%p)"]
+ local f_quadruple_pt = formatters["(%p,%p,%p,%p)"]
+
+ local r = P('%') / "percent"
+ + P('"') / "dquote"
+ + P('\n') / "crlf"
+ -- + P(' ') / "space"
+ local a = Cc("&")
+ local q = Cc('"')
+ local p = Cs(q * (r * a)^-1 * (a * r * (P(-1) + a) + P(1))^0 * q)
+
+ mp.cleaned = function(s) return lpegmatch(p,s) or s end
+
+ -- local function mpprint(...) -- we can optimize for n=1
+ -- for i=1,select("#",...) do
+ -- local value = (select(i,...))
+ -- if value ~= nil then
+ -- n = n + 1
+ -- local t = type(value)
+ -- if t == "number" then
+ -- buffer[n] = f_numeric(value)
+ -- elseif t == "string" then
+ -- buffer[n] = value
+ -- elseif t == "table" then
+ -- buffer[n] = "(" .. concat(value,",") .. ")"
+ -- else -- boolean or whatever
+ -- buffer[n] = tostring(value)
+ -- end
+ -- end
+ -- end
+ -- end
+
+ local function mpp(value)
+ n = n + 1
+ local t = type(value)
+ if t == "number" then
+ buffer[n] = f_numeric(value)
+ elseif t == "string" then
+ buffer[n] = value
+ elseif t == "table" then
+ buffer[n] = "(" .. concat(value,",") .. ")"
+ else -- boolean or whatever
+ buffer[n] = tostring(value)
+ end
+ end
+
+ local function mpprint(first,second,...)
+ if second == nil then
+ if first ~= nil then
+ mpp(first)
+ end
+ else
+ for i=1,select("#",first,second,...) do
+ local value = (select(i,first,second,...))
+ if value ~= nil then
+ mpp(value)
+ end
+ end
+ end
end
-end
-function mp.path(t,connector,cycle)
- if type(t) == "table" then
- local tn = #t
- if tn > 0 then
- if connector == true then
- connector = "--"
- cycle = true
- elseif not connector then
- connector = "--"
+ local function mpp(value)
+ n = n + 1
+ local t = type(value)
+ if t == "number" then
+ buffer[n] = f_numeric(value)
+ elseif t == "string" then
+ buffer[n] = lpegmatch(p,value)
+ elseif t == "table" then
+ if #t > 4 then
+ buffer[n] = ""
+ else
+ buffer[n] = "(" .. concat(value,",") .. ")"
end
- local ti = t[1]
- n = n + 1 ; buffer[n] = f_pair(ti[1],ti[2])
- for i=2,tn do
- local ti = t[i]
- n = n + 1 ; buffer[n] = connector
- n = n + 1 ; buffer[n] = f_pair(ti[1],ti[2])
+ else -- boolean or whatever
+ buffer[n] = tostring(value)
+ end
+ end
+
+ local function mpvprint(first,second,...) -- variable print
+ if second == nil then
+ if first ~= nil then
+ mpp(first)
end
- if cycle then
- n = n + 1 ; buffer[n] = connector
- n = n + 1 ; buffer[n] = "cycle"
+ else
+ for i=1,select("#",first,second,...) do
+ local value = (select(i,first,second,...))
+ if value ~= nil then
+ mpp(value)
+ end
end
end
end
-end
-function mp.size(t)
- n = n + 1
- buffer[n] = type(t) == "table" and f_numeric(#t) or "0"
-end
+ local function mpstring(value)
+ n = n + 1
+ buffer[n] = lpegmatch(p,value)
+ end
-local mpnamedcolor = attributes.colors.mpnamedcolor
+ local function mpboolean(b)
+ n = n + 1
+ buffer[n] = b and "true" or "false"
+ end
-mp.NamedColor = function(str)
- mpprint(mpnamedcolor(str))
-end
+ local function mpnumeric(f)
+ n = n + 1
+ if not f or f == 0 then
+ buffer[n] = "0"
+ else
+ buffer[n] = f_numeric(f)
+ end
+ end
--- experiment: names can change
+ local function mpinteger(i)
+ n = n + 1
+ -- buffer[n] = i and f_integer(i) or "0"
+ buffer[n] = i or "0"
+ end
-local datasets = { }
-mp.datasets = datasets
+ local function mppoints(i)
+ n = n + 1
+ if not i or i == 0 then
+ buffer[n] = "0pt"
+ else
+ buffer[n] = f_points(i)
+ end
+ end
-function datasets.load(tag,filename)
- if not filename then
- tag, filename = file.basename(tag), tag
+ local function mppair(x,y)
+ n = n + 1
+ if type(x) == "table" then
+ buffer[n] = f_pair(x[1],x[2])
+ else
+ buffer[n] = f_pair(x,y)
+ end
end
- local data = mp.dataset(io.loaddata(filename) or "")
- datasets[tag] = {
- Data = data,
- Line = function(n) mp.path(data[n or 1]) end,
- Size = function() mp.size(data) end,
- }
-end
---
+ local function mppairpoints(x,y)
+ n = n + 1
+ if type(x) == "table" then
+ buffer[n] = f_pair_pt(x[1],x[2])
+ else
+ buffer[n] = f_pair_pt(x,y)
+ end
+ end
+
+ local function mptriplet(x,y,z)
+ n = n + 1
+ if type(x) == "table" then
+ buffer[n] = f_triplet(x[1],x[2],x[3])
+ else
+ buffer[n] = f_triplet(x,y,z)
+ end
+ end
-local replacer = lpeg.replacer("@","%%")
+ local function mptripletpoints(x,y,z)
+ n = n + 1
+ if type(x) == "table" then
+ buffer[n] = f_triplet_pt(x[1],x[2],x[3])
+ else
+ buffer[n] = f_triplet_pt(x,y,z)
+ end
+ end
-function mp.fprint(fmt,...)
- n = n + 1
- if not find(fmt,"%",1,true) then
- fmt = lpegmatch(replacer,fmt)
+ local function mpquadruple(w,x,y,z)
+ n = n + 1
+ if type(w) == "table" then
+ buffer[n] = f_quadruple(w[1],w[2],w[3],w[4])
+ else
+ buffer[n] = f_quadruple(w,x,y,z)
+ end
end
- buffer[n] = formatters[fmt](...)
-end
-local function mpquoted(fmt,s,...)
- n = n + 1
- if s then
+ local function mpquadruplepoints(w,x,y,z)
+ n = n + 1
+ if type(w) == "table" then
+ buffer[n] = f_quadruple_pt(w[1],w[2],w[3],w[4])
+ else
+ buffer[n] = f_quadruple_pt(w,x,y,z)
+ end
+ end
+
+ -- we have three kind of connectors:
+ --
+ -- .. ... -- (true)
+
+ local function mp_path(f2,f6,t,connector,cycle)
+ if type(t) == "table" then
+ local tn = #t
+ if tn == 1 then
+ local t1 = t[1]
+ n = n + 1 ; buffer[n] = f2(t1[1],t1[2])
+ elseif tn > 0 then
+ if connector == true or connector == nil then
+ connector = ".."
+ elseif connector == false then
+ connector = "--"
+ end
+ if cycle == nil then
+ cycle = t.cycle
+ if cycle == nil then
+ cycle = true
+ end
+ end
+ local six = connector == ".." -- otherwise we use whatever gets asked for
+ local controls = connector -- whatever
+ local a = t[1]
+ local b = t[2]
+ n = n + 1
+ if six and #a == 6 and #b == 6 then
+ buffer[n] = f6(a[1],a[2],a[5],a[6],b[3],b[4])
+ controls = ".."
+ else
+ buffer[n] = f2(a[1],a[2])
+ controls = connector
+ end
+ for i=2,tn-1 do
+ a = b
+ b = t[i+1]
+ n = n + 1
+ buffer[n] = connector
+ n = n + 1
+ if six and #a == 6 and #b == 6 then
+ buffer[n] = f6(a[1],a[2],a[5],a[6],b[3],b[4])
+ controls = ".."
+ else
+ buffer[n] = f2(a[1],a[2])
+ controls = connector
+ end
+ end
+ n = n + 1
+ buffer[n] = connector
+ a = b
+ b = t[1]
+ n = n + 1
+ if cycle then
+ if six and #a == 6 and #b == 6 then
+ buffer[n] = f6(a[1],a[2],a[5],a[6],b[3],b[4])
+ controls = ".."
+ else
+ buffer[n] = f2(a[1],a[2])
+ controls = connector
+ end
+ n = n + 1
+ buffer[n] = connector
+ n = n + 1
+ buffer[n] = "cycle"
+ else
+ buffer[n] = f2(a[1],a[2])
+ end
+ end
+ end
+ end
+
+ local function mppath(...)
+ mp_path(f_pair,f_ctrl,...)
+ end
+
+ local function mppathpoints(...)
+ mp_path(f_pair_pt,f_ctrl_pt,...)
+ end
+
+ local function mpsize(t)
+ n = n + 1
+ buffer[n] = type(t) == "table" and f_numeric(#t) or "0"
+ end
+
+ local replacer = lpeg.replacer("@","%%")
+
+ local function mpfprint(fmt,...)
+ n = n + 1
if not find(fmt,"%",1,true) then
fmt = lpegmatch(replacer,fmt)
end
- -- buffer[n] = '"' .. formatters[fmt](s,...) .. '"'
- buffer[n] = lpegmatch(p,formatters[fmt](s,...))
- elseif fmt then
- -- buffer[n] = '"' .. fmt .. '"'
- buffer[n] = lpegmatch(p,fmt)
- else
- -- something is wrong
+ buffer[n] = formatters[fmt](...)
end
+
+ local function mpquoted(fmt,s,...)
+ if s then
+ n = n + 1
+ if not find(fmt,"%",1,true) then
+ fmt = lpegmatch(replacer,fmt)
+ end
+ -- buffer[n] = '"' .. formatters[fmt](s,...) .. '"'
+ buffer[n] = lpegmatch(p,formatters[fmt](s,...))
+ elseif fmt then
+ n = n + 1
+ -- buffer[n] = '"' .. fmt .. '"'
+ buffer[n] = lpegmatch(p,fmt)
+ else
+ -- something is wrong
+ end
+ end
+
+ aux.print = mpprint
+ aux.vprint = mpvprint
+ aux.boolean = mpboolean
+ aux.string = mpstring
+ aux.numeric = mpnumeric
+ aux.number = mpnumeric
+ aux.integer = mpinteger
+ aux.points = mppoints
+ aux.pair = mppair
+ aux.pairpoints = mppairpoints
+ aux.triplet = mptriplet
+ aux.tripletpoints = mptripletpoints
+ aux.quadruple = mpquadruple
+ aux.quadruplepoints = mpquadruplepoints
+ aux.path = mppath
+ aux.pathpoints = mppathpoints
+ aux.size = mpsize
+ aux.fprint = mpfprint
+ aux.quoted = mpquoted
+
+ -- we need access to the variables
+
+ function metapost.nofscriptruns()
+ return runs
+ end
+
+ -- sometimes we gain (e.g. .5 sec on the sync test)
+
+ local cache = table.makeweak()
+
+ function metapost.runscript(code)
+ nesting = nesting + 1
+ local trace = trace_enabled and trace_luarun
+ if trace then
+ report_luarun("%i: code: %s",nesting,code)
+ end
+ runs = runs + 1
+ local f = cache[code]
+ if not f then
+ f = loadstring(code .. " return mp._f_()")
+ if f then
+ cache[code] = f
+ elseif be_tolerant then
+ f = loadstring(code)
+ if f then
+ cache[code] = f
+ end
+ end
+ end
+ if f then
+ local _buffer_ = buffer
+ local _n_ = n
+ buffer = { }
+ n = 0
+ local result = f()
+ if result then
+ local t = type(result)
+ if t == "number" then
+ result = f_numeric(result)
+ elseif t ~= "string" then
+ result = tostring(result)
+ end
+ if trace then
+ if #result == 0 then
+ report_luarun("%i: no result",nesting)
+ else
+ report_luarun("%i: result: %s",nesting,result)
+ end
+ end
+ buffer = _buffer_
+ n = _n_
+ nesting = nesting - 1
+ return result
+ elseif trace then
+ report_luarun("%i: no result",nesting)
+ end
+ buffer, n = _buffer_, _n_
+ else
+ report_luarun("%i: no result, invalid code: %s",nesting,code)
+ end
+ nesting = nesting - 1
+ return ""
+ end
+
+ -- for the moment
+
+ for k, v in next, aux do mp[k] = v end
+
end
-mp.quoted = mpquoted
+do
+
+ local mpnamedcolor = attributes.colors.mpnamedcolor
+ local mpprint = aux.print
-function mp.n(t)
+ mp.mf_named_color = function(str)
+ mpprint(mpnamedcolor(str))
+ end
+
+end
+
+function mp.n(t) -- used ?
return type(t) == "table" and #t or 0
end
-local whitespace = lpegpatterns.whitespace
-local newline = lpegpatterns.newline
-local setsep = newline^2
-local comment = (S("#%") + P("--")) * (1-newline)^0 * (whitespace - setsep)^0
-local value = (1-whitespace)^1 / tonumber
-local entry = Ct( value * whitespace * value)
-local set = Ct((entry * (whitespace-setsep)^0 * comment^0)^1)
-local series = Ct((set * whitespace^0)^1)
+do
+
+ -- experiment: names can change
+
+ local mppath = aux.path
+ local mpsize = aux.size
+
+ local whitespace = lpegpatterns.whitespace
+ local newline = lpegpatterns.newline
+ local setsep = newline^2
+ local comment = (S("#%") + P("--")) * (1-newline)^0 * (whitespace - setsep)^0
+ local value = (1-whitespace)^1 / tonumber
+ local entry = Ct( value * whitespace * value)
+ local set = Ct((entry * (whitespace-setsep)^0 * comment^0)^1)
+ local series = Ct((set * whitespace^0)^1)
+
+ local pattern = whitespace^0 * series
-local pattern = whitespace^0 * series
+ local datasets = { }
+ mp.datasets = datasets
+
+ function mp.dataset(str)
+ return lpegmatch(pattern,str)
+ end
+
+ function datasets.load(tag,filename)
+ if not filename then
+ tag, filename = file.basename(tag), tag
+ end
+ local data = lpegmatch(pattern,io.loaddata(filename) or "")
+ datasets[tag] = {
+ data = data,
+ line = function(n) mppath(data[n or 1]) end,
+ size = function() mpsize(data) end,
+ }
+ end
+
+ table.setmetatablecall(datasets,function(t,k,f,...)
+ local d = datasets[k]
+ local t = type(d)
+ if t == "table" then
+ d = d[f]
+ if type(d) == "function" then
+ d(...)
+ else
+ mpvprint(...)
+ end
+ elseif t == "function" then
+ d(f,...)
+ end
+ end)
-function mp.dataset(str)
- return lpegmatch(pattern,str)
end
-- \startluacode
@@ -314,255 +617,157 @@ end
-- endfor ;
-- \stopMPpage
-local cache, n = { }, 0 -- todo: when > n then reset cache or make weak
-
-function metapost.runscript(code)
- local trace = trace_enabled and trace_luarun
- if trace then
- report_luarun("code: %s",code)
- end
- local f
- if n > 100 then
- cache = nil -- forget about caching
- f = loadstring(f_code(code))
- if not f and be_tolerant then
- f = loadstring(code)
- end
- else
- f = cache[code]
- if not f then
- f = loadstring(f_code(code))
- if f then
- n = n + 1
- cache[code] = f
- elseif be_tolerant then
- f = loadstring(code)
- if f then
- n = n + 1
- cache[code] = f
- end
- end
- end
- end
- if f then
- local result = f()
- if result then
- local t = type(result)
- if t == "number" then
- result = f_numeric(result)
- elseif t ~= "string" then
- result = tostring(result)
- end
- if trace then
- report_luarun("result: %s",result)
- end
- return result
- elseif trace then
- report_luarun("no result")
- end
- else
- report_luarun("no result, invalid code: %s",code)
- end
- return ""
-end
-
--- function metapost.initializescriptrunner(mpx)
--- mp.numeric = function(s) return mpx:get_numeric(s) end
--- mp.string = function(s) return mpx:get_string (s) end
--- mp.boolean = function(s) return mpx:get_boolean(s) end
--- mp.number = mp.numeric
--- end
-
-local get_numeric = mplib.get_numeric
-local get_string = mplib.get_string
-local get_boolean = mplib.get_boolean
-local get_number = get_numeric
-
--- function metapost.initializescriptrunner(mpx)
--- mp.numeric = function(s) return get_numeric(mpx,s) end
--- mp.string = function(s) return get_string (mpx,s) end
--- mp.boolean = function(s) return get_boolean(mpx,s) end
--- mp.number = mp.numeric
--- end
-
-local currentmpx = nil
-
-local get = { }
-mp.get = get
-
-get.numeric = function(s) return get_numeric(currentmpx,s) end
-get.string = function(s) return get_string (currentmpx,s) end
-get.boolean = function(s) return get_boolean(currentmpx,s) end
-get.number = mp.numeric
-
-function metapost.initializescriptrunner(mpx,trialrun)
- currentmpx = mpx
- if trace_luarun then
- report_luarun("type of run: %s", trialrun and "trial" or "final")
- end
- -- trace_enabled = not trialrun blocks too much
-end
-
-- texts:
-local factor = 65536*(7227/7200)
-local textexts = nil
-local mptriplet = mp.triplet
-local nbdimensions = nodes.boxes.dimensions
-
-function mp.tt_initialize(tt)
- textexts = tt
-end
+do
--- function mp.tt_wd(n)
--- local box = textexts and textexts[n]
--- mpprint(box and box.width/factor or 0)
--- end
--- function mp.tt_ht(n)
--- local box = textexts and textexts[n]
--- mpprint(box and box.height/factor or 0)
--- end
--- function mp.tt_dp(n)
--- local box = textexts and textexts[n]
--- mpprint(box and box.depth/factor or 0)
--- end
-
-function mp.tt_dimensions(n)
- local box = textexts and textexts[n]
- if box then
- -- could be made faster with nuts but not critical
- mptriplet(box.width/factor,box.height/factor,box.depth/factor)
- else
- mptriplet(0,0,0)
- end
-end
+ local mptriplet = mp.triplet
-function mp.tb_dimensions(category,name)
- local w, h, d = nbdimensions(category,name)
- mptriplet(w/factor,h/factor,d/factor)
-end
+ local bpfactor = number.dimenfactors.bp
+ local textexts = nil
+ local mptriplet = mp.triplet
+ local nbdimensions = nodes.boxes.dimensions
-function mp.report(a,b)
- if b then
- report_message("%s : %s",a,b)
- elseif a then
- report_message("%s : %s","message",a)
+ function mp.mf_tt_initialize(tt)
+ textexts = tt
end
-end
---
+ function mp.mf_tt_dimensions(n)
+ local box = textexts and textexts[n]
+ if box then
+ -- could be made faster with nuts but not critical
+ mptriplet(box.width*bpfactor,box.height*bpfactor,box.depth*bpfactor)
+ else
+ mptriplet(0,0,0)
+ end
+ end
-local hashes = { }
+ function mp.mf_tb_dimensions(category,name)
+ local w, h, d = nbdimensions(category,name)
+ mptriplet(w*bpfactor,h*bpfactor,d*bpfactor)
+ end
-function mp.newhash()
- for i=1,#hashes+1 do
- if not hashes[i] then
- hashes[i] = { }
- mpprint(i)
- return
+ function mp.report(a,b,c,...)
+ if c then
+ report_message("%s : %s",a,formatters[(gsub(b,"@","%%"))](c,...))
+ elseif b then
+ report_message("%s : %s",a,b)
+ elseif a then
+ report_message("%s : %s","message",a)
end
end
-end
-function mp.disposehash(n)
- hashes[n] = nil
end
-function mp.inhash(n,key)
- local h = hashes[n]
- mpprint(h and h[key] and true or false)
-end
+do
+
+ local mpprint = aux.print
+ local modes = tex.modes
+ local systemmodes = tex.systemmodes
-function mp.tohash(n,key)
- local h = hashes[n]
- if h then
- h[key] = true
+ function mp.mode(s)
+ mpprint(modes[s] and true or false)
end
-end
-local modes = tex.modes
-local systemmodes = tex.systemmodes
+ function mp.systemmode(s)
+ mpprint(systemmodes[s] and true or false)
+ end
-function mp.mode(s)
- mpprint(modes[s] and true or false)
-end
+ mp.processingmode = mp.mode
-function mp.systemmode(s)
- mpprint(systemmodes[s] and true or false)
end
-- for alan's nodes:
-function mp.isarray(str)
- mpprint(find(str,"%d") and true or false)
-end
+do
+
+ local mpprint = aux.print
+ local mpquoted = aux.quoted
+
+ function mp.isarray(str)
+ mpprint(find(str,"%d") and true or false)
+ end
+
+ function mp.prefix(str)
+ mpquoted(match(str,"^(.-)[%d%[]") or str)
+ end
+
+ -- function mp.dimension(str)
+ -- local n = 0
+ -- for s in gmatch(str,"%[?%-?%d+%]?") do --todo: lpeg
+ -- n = n + 1
+ -- end
+ -- mpprint(n)
+ -- end
+
+ mp.dimension = lpeg.counter(P("[") * lpegpatterns.integer * P("]") + lpegpatterns.integer,mpprint)
+
+ -- faster and okay as we don't have many variables but probably only
+ -- basename makes sense and even then it's not called that often
+
+ -- local hash = table.setmetatableindex(function(t,k)
+ -- local v = find(k,"%d") and true or false
+ -- t[k] = v
+ -- return v
+ -- end)
+ --
+ -- function mp.isarray(str)
+ -- mpprint(hash[str])
+ -- end
+ --
+ -- local hash = table.setmetatableindex(function(t,k)
+ -- local v = '"' .. (match(k,"^(.-)%d") or k) .. '"'
+ -- t[k] = v
+ -- return v
+ -- end)
+ --
+ -- function mp.prefix(str)
+ -- mpprint(hash[str])
+ -- end
-function mp.prefix(str)
- mpquoted(match(str,"^(.-)[%d%[]") or str)
end
--- function mp.dimension(str)
--- local n = 0
--- for s in gmatch(str,"%[?%-?%d+%]?") do --todo: lpeg
--- n = n + 1
--- end
--- mpprint(n)
--- end
+do
-mp.dimension = lpeg.counter(P("[") * lpegpatterns.integer * P("]") + lpegpatterns.integer,mpprint)
+ local getmacro = tex.getmacro
+ local getdimen = tex.getdimen
+ local getcount = tex.getcount
+ local gettoks = tex.gettoks
+ local setmacro = tex.setmacro
+ local setdimen = tex.setdimen
+ local setcount = tex.setcount
+ local settoks = tex.settoks
--- faster and okay as we don't have many variables but probably only
--- basename makes sense and even then it's not called that often
+ local mpprint = mp.print
+ local mpquoted = mp.quoted
--- local hash = table.setmetatableindex(function(t,k)
--- local v = find(k,"%d") and true or false
--- t[k] = v
--- return v
--- end)
---
--- function mp.isarray(str)
--- mpprint(hash[str])
--- end
---
--- local hash = table.setmetatableindex(function(t,k)
--- local v = '"' .. (match(k,"^(.-)%d") or k) .. '"'
--- t[k] = v
--- return v
--- end)
---
--- function mp.prefix(str)
--- mpprint(hash[str])
--- end
+ local bpfactor = number.dimenfactors.bp
-local getdimen = tex.getdimen
-local getcount = tex.getcount
-local gettoks = tex.gettoks
-local setdimen = tex.setdimen
-local setcount = tex.setcount
-local settoks = tex.settoks
+ -- more helpers
-local mpprint = mp.print
-local mpquoted = mp.quoted
+ local function getmacro(k) mpprint (getmacro(k)) end
+ local function getdimen(k) mpprint (getdimen(k)*bpfactor) end
+ local function getcount(k) mpprint (getcount(k)) end
+ local function gettoks (k) mpquoted(gettoks (k)) end
-local factor = number.dimenfactors.bp
+ local function setmacro(k,v) setmacro(k,v) end
+ local function setdimen(k,v) setdimen(k,v/bpfactor) end
+ local function setcount(k,v) setcount(k,v) end
+ local function settoks (k,v) settoks (k,v) end
--- more helpers
+ -- def foo = lua.mp.foo ... enddef ; % loops due to foo in suffix
-function mp.getdimen(k) mpprint (getdimen(k)*factor) end
-function mp.getcount(k) mpprint (getcount(k)) end
-function mp.gettoks (k) mpquoted(gettoks (k)) end
-function mp.setdimen(k,v) setdimen(k,v/factor) end
-function mp.setcount(k,v) setcount(k,v) end
-function mp.settoks (k,v) settoks (k,v) end
+ mp._get_macro_ = getmacro mp.getmacro = getmacro
+ mp._get_dimen_ = getdimen mp.getdimen = getdimen
+ mp._get_count_ = getcount mp.getcount = getcount
+ mp._get_toks_ = gettoks mp.gettoks = gettoks
--- def foo = lua.mp.foo ... enddef ; % loops due to foo in suffix
+ mp._set_macro_ = setmacro mp.setmacro = setmacro
+ mp._set_dimen_ = setdimen mp.setdimen = setdimen
+ mp._set_count_ = setcount mp.setcount = setcount
+ mp._set_toks_ = settoks mp.settoks = settoks
-mp._get_dimen_ = mp.getdimen
-mp._get_count_ = mp.getcount
-mp._get_toks_ = mp.gettoks
-mp._set_dimen_ = mp.setdimen
-mp._set_count_ = mp.setcount
-mp._set_toks_ = mp.settoks
+end
-- position fun
@@ -658,6 +863,21 @@ end
do
+ local mppair = mp.pair
+
+ function mp.textextanchor(s)
+ local x, y = match(s,"tx_anchor=(%S+) (%S+)") -- todo: make an lpeg
+ if x and y then
+ x = tonumber(x)
+ y = tonumber(y)
+ end
+ mppair(x or 0,y or 0)
+ end
+
+end
+
+do
+
local mprint = mp.print
local qprint = mp.quoted
local getmacro = tokens.getters.macro
@@ -674,31 +894,65 @@ end
do
- local mpvprint = mp.vprint
+ local mpprint = aux.print
+ local mpvprint = aux.vprint
- local stores = { }
+ local hashes = { }
- function mp.newstore(name)
- stores[name] = { }
+ function mp.newhash(name)
+ if name then
+ hashes[name] = { }
+ else
+ for i=1,#hashes+1 do
+ if not hashes[i] then
+ hashes[i] = { }
+ mpvprint(i)
+ return
+ end
+ end
+ end
end
- function mp.disposestore(name)
- stores[name] = nil
+ function mp.disposehash(n)
+ if tonumber(n) then
+ hashes[n] = false
+ else
+ hashes[n] = nil
+ end
end
- function mp.tostore(name,key,value)
- stores[name][key] = value
+ function mp.inhash(n,key)
+ local h = hashes[n]
+ mpvprint(h and h[key] and true or false)
end
- function mp.fromstore(name,key)
- mpvprint(stores[name][key]) -- type specific
+ function mp.tohash(n,key,value)
+ local h = hashes[n]
+ if h then
+ if value == nil then
+ h[key] = true
+ else
+ h[key] = value
+ end
+ end
+ end
+
+ function mp.fromhash(n,key)
+ local h = hashes[n]
+ mpvprint(h and h[key] or false)
end
interfaces.implement {
- name = "getMPstored",
+ name = "MPfromhash",
arguments = "2 strings",
actions = function(name,key)
- context(stores[name][key])
+ local h = hashes[name] or hashes[tonumber(name)]
+ if h then
+ local v = h[key] or h[tonumber(key)]
+ if v then
+ context(v)
+ end
+ end
end
}
@@ -706,11 +960,70 @@ end
do
- local mpprint = mp.print
- local texmodes = tex.modes
+ -- a bit overkill: just a find(str,"mf_object=") can be enough
- function mp.processingmode(s)
- mpprint(tostring(texmodes[s]))
+ local mpboolean = aux.boolean
+
+ local p1 = P("mf_object=")
+ local p2 = lpegpatterns.eol * p1
+ local pattern = (1-p2)^0 * p2 + p1
+
+ function mp.isobject(str)
+ mpboolean(pattern and str ~= "" and lpegmatch(pattern,str))
end
end
+
+do
+
+ local mpnumeric = aux.numeric
+ local mppair = aux.pair
+ local mpgetpath = get.path
+
+ local p = nil
+ local n = 0
+
+ local function mf_path_length(name)
+ p = mpgetpath(name)
+ n = p and #p or 0
+ mpnumeric(n)
+ end
+
+ local function mf_path_point(i)
+ if i > 0 and i <= n then
+ local pi = p[i]
+ mppair(pi[1],pi[2])
+ end
+ end
+
+ local function mf_path_left(i)
+ if i > 0 and i <= n then
+ local pi = p[i]
+ mppair(pi[5],pi[6])
+ end
+ end
+
+ local function mf_path_right(i)
+ if i > 0 and i <= n then
+ local pn
+ if i == 1 then
+ pn = p[2] or p[1]
+ else
+ pn = p[i+1] or p[1]
+ end
+ mppair(pn[3],pn[4])
+ end
+ end
+
+ local function mf_path_reset()
+ p = nil
+ n = 0
+ end
+
+ mp.mf_path_length = mf_path_length mp.pathlength = mf_path_length
+ mp.mf_path_point = mf_path_point mp.pathpoint = mf_path_point
+ mp.mf_path_left = mf_path_left mp.pathleft = mf_path_left
+ mp.mf_path_right = mf_path_right mp.pathright = mf_path_right
+ mp.mf_path_reset = mf_path_reset mp.pathreset = mf_path_reset
+
+end
diff --git a/tex/context/base/mkiv/mlib-pdf.lua b/tex/context/base/mkiv/mlib-pdf.lua
index 75f810fb3..92fde5e13 100644
--- a/tex/context/base/mkiv/mlib-pdf.lua
+++ b/tex/context/base/mkiv/mlib-pdf.lua
@@ -6,9 +6,8 @@ if not modules then modules = { } end modules ['mlib-pdf'] = {
license = "see context related readme files",
}
--- maybe %s is better than %f
-
-local format, concat, gsub = string.format, table.concat, string.gsub
+local gsub = string.gsub
+local concat, insert, remove = table.concat, table.insert, table.remove
local abs, sqrt, round = math.abs, math.sqrt, math.round
local setmetatable, rawset, tostring, tonumber, type = setmetatable, rawset, tostring, tonumber, type
local P, S, C, Ct, Cc, Cg, Cf, Carg = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Carg
@@ -41,23 +40,34 @@ local pdfflusher = { }
metapost.flushers.pdf = pdfflusher
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 f_f = formatters["%F"]
-
-local f_m = formatters["%F %F m"]
-local f_c = formatters["%F %F %F %F %F %F c"]
-local f_l = formatters["%F %F l"]
-local f_cm = formatters["%F %F %F %F %F %F cm"]
-local f_M = formatters["%F M"]
+local mpsliteral = nodes.pool.originliteral
+
+local f_f = formatters["%.6F"]
+local f_m = formatters["%.6F %.6F m"]
+local f_c = formatters["%.6F %.6F %.6F %.6F %.6F %.6F c"]
+local f_l = formatters["%.6F %.6F l"]
+local f_cm = formatters["%.6F %.6F %.6F %.6F %.6F %.6F cm"]
+local f_M = formatters["%.6F M"]
local f_j = formatters["%i j"]
local f_J = formatters["%i J"]
-local f_d = formatters["[%s] %F d"]
-local f_w = formatters["%F w"]
+local f_d = formatters["[%s] %.6F d"]
+local f_w = formatters["%.3F w"]
+
+directives.register("metapost.stripzeros",function()
+ f_f = formatters["%.6N"]
+ f_m = formatters["%.6N %.6N m"]
+ f_c = formatters["%.6N %.6N %.6N %.6N %.6N %.6N c"]
+ f_l = formatters["%.6N %.6N l"]
+ f_cm = formatters["%.6N %.6N %.6N %.6N %.6N %.6N cm"]
+ f_M = formatters["%.6N M"]
+ f_j = formatters["%i j"]
+ f_J = formatters["%i J"]
+ f_d = formatters["[%s] %.6N d"]
+ f_w = formatters["%.3N w"]
+end)
directives.register("metapost.savetable",function(v)
if type(v) == "string" then
@@ -73,60 +83,28 @@ trackers.register("metapost.forcestroke",function(v)
force_stroke = v
end)
-local pdfliteral = function(pdfcode)
- local literal = copy_node(mpsliteral)
- literal.data = pdfcode
- 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.
local function getobjects(result,figure,index)
- if metapost.optimize then
- local robjects = result.objects
- if not robjects then
- robjects = { }
- result.objects = robjects
- end
- local fobjects = robjects[index or 1]
- if not fobjects then
- fobjects = figure:objects()
- robjects[index] = fobjects
- end
- return fobjects
- else
- return figure:objects()
- end
+ return figure:objects()
end
-function metapost.convert(result, trialrun, flusher, multipass, askedfig)
- if trialrun then
- local multipassindeed = metapost.parse(result,askedfig)
- if multipass and not multipassindeed and metapost.optimize then
- if save_table then
- table.save(save_table,metapost.totable(result,1)) -- direct
- end
- metapost.flush(result,flusher,askedfig) -- saves a run
- else
- return false
- end
- else
- if save_table then
- table.save(save_table,metapost.totable(result,1)) -- direct
- end
- metapost.flush(result,flusher,askedfig)
+function metapost.convert(specification,result)
+ local flusher = specification.flusher
+ local askedfig = specification.askedfig
+ if save_table then
+ table.save(save_table,metapost.totable(result,1)) -- direct
end
+ metapost.flush(specification,result)
return true -- done
end
function metapost.flushliteral(d)
if savedliterals then
- local literal = copy_node(mpsliteral)
- literal.data = savedliterals[d]
- write_node(literal)
+ write_node(mpsliteral(savedliterals[d]))
else
report_metapost("problem flushing literal %a",d)
end
@@ -140,7 +118,7 @@ function pdfflusher.comment(message)
if message then
message = formatters["%% mps graphic %s: %s"](metapost.n,message)
if experiment then
- context(pdfliteral(message))
+ context(mpsliteral(message))
elseif savedliterals then
local last = #savedliterals + 1
savedliterals[last] = message
@@ -169,7 +147,7 @@ function pdfflusher.flushfigure(pdfliterals) -- table
if #pdfliterals > 0 then
pdfliterals = concat(pdfliterals,"\n")
if experiment then
- context(pdfliteral(pdfliterals))
+ context(mpsliteral(pdfliterals))
else
if savedliterals then
local last = #savedliterals + 1
@@ -320,15 +298,6 @@ local p_boolean = P("false") * Cc(false) + P("true") * Cc(true)
local p_set = Ct(number^1)
local p_path = Ct(Ct(number * number^-5)^1)
--- local variable =
--- P("1:") * key * p_number
--- + P("2:") * key * p_string
--- + P("3:") * key * p_boolean
--- + S("4568") * P(":") * key * p_set
--- + P("7:") * key * p_path
---
--- local pattern_key = Cf ( Carg(1) * (Cg(variable * newline^0)^0), rawset)
-
local variable =
P("1:") * p_number
+ P("2:") * p_string
@@ -374,7 +343,9 @@ function metapost.processspecial(str)
end
end
-local function setproperties(figure)
+local stack = { }
+
+local function pushproperties(figure)
local boundingbox = figure:boundingbox()
local properties = {
llx = boundingbox[1],
@@ -388,313 +359,321 @@ local function setproperties(figure)
italic = figure:italcorr(),
number = figure:charcode() or 0,
}
+ insert(stack,properties)
metapost.properties = properties
return properties
end
+local function popproperties()
+ metapost.properties = remove(stack)
+end
+
local function nocomment() end
metapost.comment = nocomment
-function metapost.flush(result,flusher,askedfig)
+function metapost.flush(specification,result)
if result then
- local figures = result.fig
+ local flusher = specification.flusher
+ local askedfig = specification.askedfig
+ local incontext = specification.incontext
+ local figures = result.fig
if figures then
flusher = flusher or pdfflusher
- local resetplugins = metapost.resetplugins or ignore -- before figure
- local processplugins = metapost.processplugins or ignore -- each object
+ local resetplugins = metapost.resetplugins or ignore -- before figure
+ local processplugins = metapost.processplugins or ignore -- each object
local synchronizeplugins = metapost.synchronizeplugins or ignore
- local pluginactions = metapost.pluginactions or ignore -- before / after
- local startfigure = flusher.startfigure
- local stopfigure = flusher.stopfigure
- local flushfigure = flusher.flushfigure
- local textfigure = flusher.textfigure
- local processspecial = flusher.processspecial or metapost.processspecial
- metapost.comment = flusher.comment or nocomment
+ local pluginactions = metapost.pluginactions or ignore -- before / after
+ local startfigure = flusher.startfigure
+ local stopfigure = flusher.stopfigure
+ local flushfigure = flusher.flushfigure
+ local textfigure = flusher.textfigure
+ local processspecial = flusher.processspecial or metapost.processspecial
+ metapost.comment = flusher.comment or nocomment
for index=1,#figures do
- local figure = figures[index]
- local properties = setproperties(figure)
+ local figure = figures[index]
+ local properties = pushproperties(figure)
if askedfig == "direct" or askedfig == "all" or askedfig == properties.number then
- local objects = getobjects(result,figure,index)
- local result = { }
- local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
- local llx = properties.llx
- local lly = properties.lly
- local urx = properties.urx
- local ury = properties.ury
+ local objects = getobjects(result,figure,index)
+ local result = { }
+ local miterlimit = -1
+ local linecap = -1
+ local linejoin = -1
+ local dashed = false
+ local llx = properties.llx
+ local lly = properties.lly
+ local urx = properties.urx
+ local ury = properties.ury
if urx < llx then
-- invalid
startfigure(properties.number,0,0,0,0,"invalid",figure)
stopfigure()
else
- startfigure(properties.number,llx,lly,urx,ury,"begin",figure)
- result[#result+1] = "q"
- if objects then
- resetplugins(result) -- we should move the colorinitializer here
- local savedpath = nil
- local savedhtap = nil
- for o=1,#objects do
- local object = objects[o]
- local objecttype = object.type
- if objecttype == "text" then
- result[#result+1] = "q"
- local ot = object.transform -- 3,4,5,6,1,2
- result[#result+1] = f_cm(ot[3],ot[4],ot[5],ot[6],ot[1],ot[2]) -- TH: formatters["%F %F m %F %F %F %F 0 0 cm"](unpack(ot))
- flushfigure(result) -- flush accumulated literals
- result = { }
- textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth)
- result[#result+1] = "Q"
- elseif objecttype == "special" then
- if processspecial then
- processspecial(object.prescript)
- end
- elseif objecttype == "start_clip" then
- local evenodd = not object.istext and object.postscript == "evenodd"
- result[#result+1] = "q"
- flushnormalpath(object.path,result,false)
- result[#result+1] = evenodd and "W* n" or "W n"
- elseif objecttype == "stop_clip" then
- result[#result+1] = "Q"
- miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false
- elseif objecttype == "start_bounds" or objecttype == "stop_bounds" then
- -- skip
- else
- -- we use an indirect table as we want to overload
- -- entries but this is not possible in userdata
- --
- -- can be optimized if no path
- --
- local original = object
- local object = { }
- setmetatable(object, {
- __index = original
- })
- -- first we analyze
- local before, after = processplugins(object)
- local evenodd, collect, both = false, false, false
- local postscript = object.postscript
- if not object.istext then
- if postscript == "evenodd" then
- evenodd = true
- elseif postscript == "collect" then
- collect = true
- elseif postscript == "both" then
- both = true
- elseif postscript == "eoboth" then
- evenodd = true
- both = true
- end
- end
- --
- if collect then
- if not savedpath then
- savedpath = { object.path or false }
- savedhtap = { object.htap or false }
- else
- savedpath[#savedpath+1] = object.path or false
- savedhtap[#savedhtap+1] = object.htap or false
+
+ -- we need to be indirect if we want the one-pass solution
+
+ local function processfigure()
+ result[#result+1] = "q"
+ if objects then
+ -- resetplugins(result) -- we should move the colorinitializer here
+ local savedpath = nil
+ local savedhtap = nil
+ for o=1,#objects do
+ local object = objects[o]
+ local objecttype = object.type
+ if objecttype == "text" then
+ result[#result+1] = "q"
+ local ot = object.transform -- 3,4,5,6,1,2
+ result[#result+1] = f_cm(ot[3],ot[4],ot[5],ot[6],ot[1],ot[2])
+ flushfigure(result) -- flush accumulated literals
+ result = { }
+ textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth)
+ result[#result+1] = "Q"
+ elseif objecttype == "special" then
+ if processspecial then
+ processspecial(object.prescript)
end
+ elseif objecttype == "start_clip" then
+ local evenodd = not object.istext and object.postscript == "evenodd"
+ result[#result+1] = "q"
+ flushnormalpath(object.path,result,false)
+ result[#result+1] = evenodd and "W* n" or "W n"
+ elseif objecttype == "stop_clip" then
+ result[#result+1] = "Q"
+ miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false
+ elseif objecttype == "start_bounds" or objecttype == "stop_bounds" then
+ -- skip
else
- local objecttype = object.type -- can have changed
- if before then
- result = pluginactions(before,result,flushfigure)
- end
- local ml = object.miterlimit
- if ml and ml ~= miterlimit then
- miterlimit = ml
- result[#result+1] = f_M(ml)
- end
- local lj = object.linejoin
- if lj and lj ~= linejoin then
- linejoin = lj
- result[#result+1] = f_j(lj)
- end
- local lc = object.linecap
- if lc and lc ~= linecap then
- linecap = lc
- result[#result+1] = f_J(lc)
+ -- we use an indirect table as we want to overload
+ -- entries but this is not possible in userdata
+ --
+ -- can be optimized if no path
+ --
+ local original = object
+ local object = { }
+ setmetatable(object, {
+ __index = original
+ })
+ local before,
+ after = processplugins(object)
+ local evenodd = false
+ local collect = false
+ local both = false
+ local postscript = object.postscript
+ if not object.istext then
+ if postscript == "evenodd" then
+ evenodd = true
+ elseif postscript == "collect" then
+ collect = true
+ elseif postscript == "both" then
+ both = true
+ elseif postscript == "eoboth" then
+ evenodd = true
+ both = true
+ end
end
- if both then
- if dashed ~= false then -- was just dashed test
- result[#result+1] = "[] 0 d"
- dashed = false
+ --
+ if collect then
+ if not savedpath then
+ savedpath = { object.path or false }
+ savedhtap = { object.htap or false }
+ else
+ savedpath[#savedpath+1] = object.path or false
+ savedhtap[#savedhtap+1] = object.htap or false
end
else
- local dl = object.dash
- if dl then
- local d = f_d(concat(dl.dashes or {}," "),dl.offset)
- if d ~= dashed then
- dashed = d
- result[#result+1] = d
- end
- elseif dashed ~= false then -- was just dashed test
- result[#result+1] = "[] 0 d"
- dashed = false
+ local objecttype = object.type -- can have changed
+ if before then
+ result = pluginactions(before,result,flushfigure)
end
- end
- local path = object.path -- newpath
- local transformed, penwidth = false, 1
- local open = path and path[1].left_type and path[#path].right_type -- at this moment only "end_point"
- local pen = object.pen
- if pen then
- if pen.type == 'elliptical' then
- transformed, penwidth = pen_characteristics(original) -- boolean, value
- result[#result+1] = f_w(penwidth) -- todo: only if changed
- if objecttype == 'fill' then
- objecttype = 'both'
+ local ml = object.miterlimit
+ if ml and ml ~= miterlimit then
+ miterlimit = ml
+ result[#result+1] = f_M(ml)
+ end
+ local lj = object.linejoin
+ if lj and lj ~= linejoin then
+ linejoin = lj
+ result[#result+1] = f_j(lj)
+ end
+ local lc = object.linecap
+ if lc and lc ~= linecap then
+ linecap = lc
+ result[#result+1] = f_J(lc)
+ end
+ if both then
+ if dashed ~= false then -- was just dashed test
+ result[#result+1] = "[] 0 d"
+ dashed = false
end
- else -- calculated by mplib itself
- objecttype = 'fill'
- end
- end
- if transformed then
- result[#result+1] = "q"
- end
- if path then
- if savedpath then
- for i=1,#savedpath do
- local path = savedpath[i]
- if transformed then
- flushconcatpath(path,result,open)
- else
- flushnormalpath(path,result,open)
+ else
+ local dl = object.dash
+ if dl then
+ local d = f_d(concat(dl.dashes or {}," "),dl.offset)
+ if d ~= dashed then
+ dashed = d
+ result[#result+1] = d
end
+ elseif dashed ~= false then -- was just dashed test
+ result[#result+1] = "[] 0 d"
+ dashed = false
end
- savedpath = nil
end
- if transformed then
- flushconcatpath(path,result,open)
- else
- flushnormalpath(path,result,open)
- end
- if force_stroke then
- result[#result+1] = open and "S" or "h S"
- elseif objecttype == "fill" then
- result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo
- elseif objecttype == "outline" then
- if both then
- result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo
- else
- result[#result+1] = open and "S" or "h S"
- end
- elseif objecttype == "both" then
- result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo -- b includes closepath
+ local path = object.path -- newpath
+ local transformed = false
+ local penwidth = 1
+ local open = path and path[1].left_type and path[#path].right_type -- at this moment only "end_point"
+ local pen = object.pen
+ if pen then
+ if pen.type == "elliptical" then
+ transformed, penwidth = pen_characteristics(original) -- boolean, value
+ result[#result+1] = f_w(penwidth) -- todo: only if changed
+ if objecttype == "fill" then
+ objecttype = "both"
+ end
+ else -- calculated by mplib itself
+ objecttype = "fill"
+ end
end
- end
- if transformed then
- result[#result+1] = "Q"
- end
- local path = object.htap
- if path then
if transformed then
result[#result+1] = "q"
end
- if savedhtap then
- for i=1,#savedhtap do
- local path = savedhtap[i]
- if transformed then
- flushconcatpath(path,result,open)
+ if path then
+ if savedpath then
+ for i=1,#savedpath do
+ local path = savedpath[i]
+ if transformed then
+ flushconcatpath(path,result,open)
+ else
+ flushnormalpath(path,result,open)
+ end
+ end
+ savedpath = nil
+ end
+ if transformed then
+ flushconcatpath(path,result,open)
+ else
+ flushnormalpath(path,result,open)
+ end
+ if force_stroke then
+ result[#result+1] = open and "S" or "h S"
+ elseif objecttype == "fill" then
+ result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo
+ elseif objecttype == "outline" then
+ if both then
+ result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo
else
- flushnormalpath(path,result,open)
+ result[#result+1] = open and "S" or "h S"
end
+ elseif objecttype == "both" then
+ result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo -- b includes closepath
end
- savedhtap = nil
- evenodd = true
end
if transformed then
- flushconcatpath(path,result,open)
- else
- flushnormalpath(path,result,open)
+ result[#result+1] = "Q"
end
- if force_stroke then
- result[#result+1] = open and "S" or "h S"
- elseif objecttype == "fill" then
- result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo
- elseif objecttype == "outline" then
- result[#result+1] = open and "S" or "h S"
- elseif objecttype == "both" then
- result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo -- b includes closepath
+ local path = object.htap
+ if path then
+ if transformed then
+ result[#result+1] = "q"
+ end
+ if savedhtap then
+ for i=1,#savedhtap do
+ local path = savedhtap[i]
+ if transformed then
+ flushconcatpath(path,result,open)
+ else
+ flushnormalpath(path,result,open)
+ end
+ end
+ savedhtap = nil
+ evenodd = true
+ end
+ if transformed then
+ flushconcatpath(path,result,open)
+ else
+ flushnormalpath(path,result,open)
+ end
+ if force_stroke then
+ result[#result+1] = open and "S" or "h S"
+ elseif objecttype == "fill" then
+ result[#result+1] = evenodd and "h f*" or "h f" -- f* = eo
+ elseif objecttype == "outline" then
+ result[#result+1] = open and "S" or "h S"
+ elseif objecttype == "both" then
+ result[#result+1] = evenodd and "h B*" or "h B" -- B* = eo -- b includes closepath
+ end
+ if transformed then
+ result[#result+1] = "Q"
+ end
end
- if transformed then
- result[#result+1] = "Q"
+ if after then
+ result = pluginactions(after,result,flushfigure)
end
end
- if after then
- result = pluginactions(after,result,flushfigure)
+ if object.grouped then
+ -- can be qQ'd so changes can end up in groups
+ miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false
end
end
- if object.grouped then
- -- can be qQ'd so changes can end up in groups
- miterlimit, linecap, linejoin, dashed = -1, -1, -1, "" -- was false
- end
end
end
+ result[#result+1] = "Q"
+ flushfigure(result)
+ end
+ startfigure(properties.number,llx,lly,urx,ury,"begin",figure)
+ if incontext then
+ context(function() processfigure() end)
+ else
+ processfigure()
end
- result[#result+1] = "Q"
- flushfigure(result)
stopfigure("end")
+
end
if askedfig ~= "all" then
break
end
end
+ popproperties()
end
metapost.comment = nocomment
+ resetplugins(result) -- we should move the colorinitializer here
end
end
end
-function metapost.parse(result,askedfig)
- if result then
- local figures = result.fig
- if figures then
- local multipass = false
- local analyzeplugins = metapost.analyzeplugins -- each object
- for index=1,#figures do
- local figure = figures[index]
- local properties = setproperties(figure)
- if askedfig == "direct" or askedfig == "all" or askedfig == properties.number then
- local objects = getobjects(result,figure,index)
- if objects then
- for o=1,#objects do
- if analyzeplugins(objects[o]) then
- multipass = true
- end
- end
- end
- if askedfig ~= "all" then
- break
- end
- end
+-- tracing:
+
+do
+
+ local result = { }
+
+ local flusher = {
+ startfigure = function()
+ result = { }
+ context.startnointerference()
+ end,
+ flushfigure = function(literals)
+ local n = #result
+ for i=1,#literals do
+ result[n+i] = literals[i]
end
- return multipass
+ end,
+ stopfigure = function()
+ context.stopnointerference()
end
- end
-end
+ }
--- tracing:
+ local specification = {
+ flusher = flusher,
+ -- incontext = true,
+ }
-local result = { }
-
-local flusher = {
- startfigure = function()
- result = { }
- context.startnointerference()
- end,
- flushfigure = function(literals)
- local n = #result
- for i=1,#literals do
- result[n+i] = literals[i]
- end
- end,
- stopfigure = function()
- context.stopnointerference()
+ function metapost.pdfliterals(result)
+ metapost.flush(specification,result)
+ return result
end
-}
-function metapost.pdfliterals(result)
- metapost.flush(result,flusher)
- return result
end
function metapost.totable(result,askedfig)
@@ -702,7 +681,6 @@ function metapost.totable(result,askedfig)
local figure = result and result.fig and result.fig[1]
if figure then
local results = { }
- -- local objects = figure:objects()
local objects = getobjects(result,figure,askedfig)
for o=1,#objects do
local object = objects[o]
diff --git a/tex/context/base/mkiv/mlib-pdf.mkiv b/tex/context/base/mkiv/mlib-pdf.mkiv
index 147b67f74..6dc73a153 100644
--- a/tex/context/base/mkiv/mlib-pdf.mkiv
+++ b/tex/context/base/mkiv/mlib-pdf.mkiv
@@ -47,6 +47,18 @@
\global\MPurx \zeropoint
\global\MPury \zeropoint}
+\let\popMPboundingbox\relax
+
+\unexpanded\def\pushMPboundingbox
+ {\edef\popMPboundingbox
+ {\global\MPwidth \the\MPwidth
+ \global\MPheight\the\MPheight
+ \global\MPllx \the\MPllx
+ \global\MPlly \the\MPlly
+ \global\MPurx \the\MPurx
+ \global\MPury \the\MPury
+ \relax}}
+
\unexpanded\def\repositionMPboxindeed
{\setbox\MPbox\hpack\bgroup
\kern-\MPllx
@@ -76,15 +88,15 @@
\wd\MPbox\MPwidth
\ht\MPbox\MPheight}
-\unexpanded\def\MPtextext#1#2#3#4#5% beware: we use a different method now (see mlib-pps)
- {\begingroup
- \setbox\MPbox\hbox{\font\temp=#1\space at #2\onebasepoint \let\c\char \temp #3}% text
- \MPllx-#4\onebasepoint
- \MPlly-#5\onebasepoint
- \repositionMPbox
- \smashbox\MPbox
- \box\MPbox
- \endgroup}
+% \unexpanded\def\MPtextext#1#2#3#4#5% beware: we use a different method now (see mlib-pps)
+% {\begingroup
+% \setbox\MPbox\hbox{\font\temp=#1\space at #2\onebasepoint \let\c\char \temp #3}% text
+% \MPllx-#4\onebasepoint
+% \MPlly-#5\onebasepoint
+% \repositionMPbox
+% \smashbox\MPbox
+% \box\MPbox
+% \endgroup}
% MPLIB specific:
diff --git a/tex/context/base/mkiv/mlib-pps.lua b/tex/context/base/mkiv/mlib-pps.lua
index bb5ce31e5..5708577fe 100644
--- a/tex/context/base/mkiv/mlib-pps.lua
+++ b/tex/context/base/mkiv/mlib-pps.lua
@@ -6,8 +6,8 @@ if not modules then modules = { } end modules ['mlib-pps'] = {
license = "see context related readme files",
}
-local format, gmatch, match, split = string.format, string.gmatch, string.match, string.split
-local tonumber, type, unpack, next = tonumber, type, unpack, next
+local format, gmatch, match, split, gsub = string.format, string.gmatch, string.match, string.split, string.gsub
+local tonumber, type, unpack, next, select = tonumber, type, unpack, next, select
local round, sqrt, min, max = math.round, math.sqrt, math.min, math.max
local insert, remove, concat = table.insert, table.remove, table.concat
local Cs, Cf, C, Cg, Ct, P, S, V, Carg = lpeg.Cs, lpeg.Cf, lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.S, lpeg.V, lpeg.Carg
@@ -23,7 +23,6 @@ local context = context
local implement = interfaces.implement
local setmacro = interfaces.setmacro
------ texgetbox = tex.getbox
local texsetbox = tex.setbox
local textakebox = tex.takebox -- or: nodes.takebox
local copy_list = node.copy_list
@@ -37,6 +36,7 @@ local stoptiming = statistics.stoptiming
local trace_runs = false trackers.register("metapost.runs", function(v) trace_runs = v end)
local trace_textexts = false trackers.register("metapost.textexts", function(v) trace_textexts = v end)
local trace_scripts = false trackers.register("metapost.scripts", function(v) trace_scripts = v end)
+local trace_btexetex = false trackers.register("metapost.btexetex", function(v) trace_btexetex = v end)
local report_metapost = logs.reporter("metapost")
local report_textexts = logs.reporter("metapost","textexts")
@@ -57,9 +57,6 @@ local cmyktorgb = colors.cmyktorgb -- or function() return 0,0,0 e
local rgbtogray = colors.rgbtogray -- or function() return 0 end
local cmyktogray = colors.cmyktogray -- or function() return 0 end
-metapost.makempy = metapost.makempy or { nofconverted = 0 }
-local makempy = metapost.makempy
-
local nooutercolor = "0 g 0 G"
local nooutertransparency = "/Tr0 gs" -- only when set
local outercolormode = 0
@@ -97,14 +94,25 @@ end
local f_f = formatters["%F"]
local f_f3 = formatters["%.3F"]
-
local f_gray = formatters["%.3F g %.3F G"]
local f_rgb = formatters["%.3F %.3F %.3F rg %.3F %.3F %.3F RG"]
local f_cmyk = formatters["%.3F %.3F %.3F %.3F k %.3F %.3F %.3F %.3F K"]
-local f_cm = formatters["q %F %F %F %F %F %F cm"]
-local f_shade = formatters["MpSh%s"]
+local f_cm_b = formatters["q %.6F %.6F %.6F %.6F %.6F %.6F cm"]
+local f_scn = formatters["%.3F"]
+local f_shade = formatters["MpSh%s"]
local f_spot = formatters["/%s cs /%s CS %s SCN %s scn"]
+local s_cm_e = "Q"
+
+directives.register("metapost.stripzeros",function()
+ f_f = formatters["%N"]
+ f_f3 = formatters["%.3N"]
+ f_gray = formatters["%.3N g %.3N G"]
+ f_rgb = formatters["%.3N %.3N %.3N rg %.3N %.3N %.3N RG"]
+ f_cmyk = formatters["%.3N %.3N %.3N %.3N k %.3N %.3N %.3N %.3N K"]
+ f_cm_b = formatters["q %.6N %.6N %.6N %.6N %.6N %.6N cm"]
+ f_scn = formatters["%.3N"]
+end)
local function checked_color_pair(color,...)
if not color then
@@ -194,7 +202,8 @@ local function checkandconvert(ca,cb,model)
ca = { cmyktorgb(ca[1],ca[2],ca[3],ca[4]) }
cb = { cmyktorgb(cb[1],cb[2],cb[3],cb[4]) }
elseif #ca == 1 then
- local a, b = 1-ca[1], 1-cb[1]
+ local a = 1 - ca[1]
+ local b = 1 - cb[1]
ca = { a, a, a }
cb = { b, b, b }
end
@@ -244,16 +253,18 @@ local function preset(t,k)
return v
end
-local function startjob(plugmode)
+local function startjob(plugmode,kind)
+ insert(stack,top)
top = {
- textexts = { }, -- all boxes, optionally with a different color
- texlast = 0,
- texdata = setmetatableindex({},preset), -- references to textexts in order or usage
- plugmode = plugmode, -- some day we can then skip all pre/postscripts
+ textexts = { }, -- all boxes, optionally with a different color
+ texstrings = { },
+ texlast = 0,
+ texdata = setmetatableindex({},preset), -- references to textexts in order or usage
+ plugmode = plugmode, -- some day we can then skip all pre/postscripts
}
- insert(stack,top)
if trace_runs then
- report_metapost("starting run at level %i",#stack)
+ report_metapost("starting %s run at level %i in %s mode",
+ kind,#stack+1,plugmode and "plug" or "normal")
end
return top
end
@@ -261,16 +272,17 @@ end
local function stopjob()
if top then
for slot, content in next, top.textexts do
- flush_list(content)
- if trace_textexts then
- report_textexts("freeing text %s",slot)
+ if content then
+ flush_list(content)
+ if trace_textexts then
+ report_textexts("freeing text %s",slot)
+ end
end
end
if trace_runs then
- report_metapost("stopping run at level %i",#stack)
+ report_metapost("stopping run at level %i",#stack+1)
end
- remove(stack)
- top = stack[#stack]
+ top = remove(stack)
return top
end
end
@@ -281,7 +293,7 @@ end
-- end of new
-local function settext(box,slot)
+local settext = function(box,slot,str)
if top then
-- if trace_textexts then
-- report_textexts("getting text %s from box %s",slot,box)
@@ -290,10 +302,10 @@ local function settext(box,slot)
end
end
-local function gettext(box,slot)
+local gettext = function(box,slot)
if top then
- -- maybe check how often referenced
- texsetbox(box,copy_list(top.textexts[slot]))
+ texsetbox(box,top.textexts[slot])
+ top.textexts[slot] = false
-- if trace_textexts then
-- report_textexts("putting text %s in box %s",slot,box)
-- end
@@ -323,14 +335,19 @@ function models.all(cr)
local s = cr[1]
return checked_color_pair(f_gray,s,s)
elseif n == 3 then
- local r, g, b = cr[1], cr[2], cr[3]
+ local r = cr[1]
+ local g = cr[2]
+ local b = cr[3]
if r == g and g == b then
return checked_color_pair(f_gray,r,r)
else
return checked_color_pair(f_rgb,r,g,b,r,g,b)
end
else
- local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ local c = cr[1]
+ local m = cr[2]
+ local y = cr[3]
+ local k = cr[4]
if c == m and m == y and y == 0 then
k = 1 - k
return checked_color_pair(f_gray,k,k)
@@ -342,10 +359,15 @@ function models.all(cr)
local s = cr[1]
return checked_color_pair(f_gray,s,s)
elseif n == 3 then
- local r, g, b = cr[1], cr[2], cr[3]
+ local r = cr[1]
+ local g = cr[2]
+ local b = cr[3]
return checked_color_pair(f_rgb,r,g,b,r,g,b)
else
- local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ local c = cr[1]
+ local m = cr[2]
+ local y = cr[3]
+ local k = cr[4]
return checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k)
end
end
@@ -359,14 +381,19 @@ function models.rgb(cr)
local s = cr[1]
checked_color_pair(f_gray,s,s)
elseif n == 3 then
- local r, g, b = cr[1], cr[2], cr[3]
+ local r = cr[1]
+ local g = cr[2]
+ local b = cr[3]
if r == g and g == b then
return checked_color_pair(f_gray,r,r)
else
return checked_color_pair(f_rgb,r,g,b,r,g,b)
end
else
- local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ local c = cr[1]
+ local m = cr[2]
+ local y = cr[3]
+ local k = cr[4]
if c == m and m == y and y == 0 then
k = 1 - k
return checked_color_pair(f_gray,k,k)
@@ -379,11 +406,12 @@ function models.rgb(cr)
local s = cr[1]
return checked_color_pair(f_gray,s,s)
else
+ local r = cr[1]
+ local g = cr[2]
+ local b = cr[3]
local r, g, b
if n == 3 then
- r, g, b = cmyktorgb(cr[1],cr[2],cr[3],cr[4])
- else
- r, g, b = cr[1], cr[2], cr[3]
+ r, g, b = cmyktorgb(r,g,b,cr[4])
end
return checked_color_pair(f_rgb,r,g,b,r,g,b)
end
@@ -398,7 +426,9 @@ function models.cmyk(cr)
local s = cr[1]
return checked_color_pair(f_gray,s,s)
elseif n == 3 then
- local r, g, b = cr[1], cr[2], cr[3]
+ local r = cr[1]
+ local g = cr[2]
+ local b = cr[3]
if r == g and g == b then
return checked_color_pair(f_gray,r,r)
else
@@ -406,7 +436,10 @@ function models.cmyk(cr)
return checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k)
end
else
- local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ local c = cr[1]
+ local m = cr[2]
+ local y = cr[3]
+ local k = cr[4]
if c == m and m == y and y == 0 then
k = k - 1
return checked_color_pair(f_gray,k,k)
@@ -418,18 +451,20 @@ function models.cmyk(cr)
local s = cr[1]
return checked_color_pair(f_gray,s,s)
else
- local c, m, y, k
+ local c = cr[1]
+ local m = cr[2]
+ local y = cr[3]
+ local k = cr[4]
if n == 3 then
- c, m, y, k = rgbtocmyk(cr[1],cr[2],cr[3])
- else
- c, m, y, k = cr[1], cr[2], cr[3], cr[4]
+ c, m, y, k = rgbtocmyk(c,m,y)
end
return checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k)
end
end
function models.gray(cr)
- local n, s = #cr, 0
+ local n = #cr
+ local s = 0
if n == 0 then
return checked_color_pair()
elseif n == 4 then
@@ -454,76 +489,9 @@ setmetatableindex(models, function(t,k)
end)
local function colorconverter(cs)
- -- return models[colors.currentmodel()](cs)
return models[outercolormodel](cs)
end
-local btex = P("btex")
-local etex = P(" etex")
-local vtex = P("verbatimtex")
-local ttex = P("textext")
-local gtex = P("graphictext")
-local multipass = P("forcemultipass")
-local spacing = S(" \n\r\t\v")^0
-local dquote = P('"')
-
-local found, forced = false, false
-
-local function convert(str)
- found = true
- return "rawtextext(\"" .. str .. "\")" -- centered
-end
-local function ditto(str)
- return "\" & ditto & \""
-end
-local function register()
- found = true
-end
-local function force()
- forced = true
-end
-
-local texmess = (dquote/ditto + (1 - etex))^0
-
-local function ignore(s)
- report_metapost("ignoring verbatim tex: %s",s)
- return ""
-end
-
--- local parser = P {
--- [1] = Cs((V(2)/register + V(4)/ignore + V(3)/convert + V(5)/force + 1)^0),
--- [2] = ttex + gtex,
--- [3] = btex * spacing * Cs(texmess) * etex,
--- [4] = vtex * spacing * Cs(texmess) * etex,
--- [5] = multipass, -- experimental, only for testing
--- }
-
--- currently a a one-liner produces less code
-
--- textext.*(".*") can have "'s but tricky parsing as we can have concatenated strings
--- so this is something for a boring plane or train trip and we might assume proper mp
--- input anyway
-
-local parser = Cs((
- (ttex + gtex)/register
- + (btex * spacing * Cs(texmess) * etex)/convert
- + (vtex * spacing * Cs(texmess) * etex)/ignore
- + 1
-)^0)
-
-local checking_enabled = false directives.register("metapost.checktexts",function(v) checking_enabled = v end)
-
-local function checktexts(str)
- if checking_enabled then
- found, forced = false, false
- return lpegmatch(parser,str), found, forced
- else
- return str
- end
-end
-
-metapost.checktexts = checktexts
-
local factor = 65536*(7227/7200)
implement {
@@ -541,42 +509,15 @@ local function sxsy(wd,ht,dp) -- helper for text
return (wd ~= 0 and factor/wd) or 0, (hd ~= 0 and factor/hd) or 0
end
+metapost.sxsy = sxsy
+
-- for stock mp we need to declare the booleans first
-local no_first_run = "boolean mfun_first_run ; mfun_first_run := false ;"
-local do_first_run = "boolean mfun_first_run ; mfun_first_run := true ;"
-local no_trial_run = "boolean mfun_trial_run ; mfun_trial_run := false ;"
-local do_trial_run = "boolean mfun_trial_run ; mfun_trial_run := true ;"
local do_begin_fig = "; beginfig(1) ; "
local do_end_fig = "; endfig ;"
local do_safeguard = ";"
--- local f_text_data = formatters["mfun_tt_w[%i] := %f ; mfun_tt_h[%i] := %f ; mfun_tt_d[%i] := %f ;"]
---
--- function metapost.textextsdata()
--- local textexts = top.textexts
--- local collected = { }
--- local nofcollected = 0
--- for k, data in sortedhash(top.texdata) do -- sort is nicer in trace
--- local texorder = data.texorder
--- for n=1,#texorder do
--- local box = textexts[texorder[n]]
--- if box then
--- local wd, ht, dp = box.width/factor, box.height/factor, box.depth/factor
--- if trace_textexts then
--- report_textexts("passed data item %s:%s > (%p,%p,%p)",k,n,wd,ht,dp)
--- end
--- nofcollected = nofcollected + 1
--- collected[nofcollected] = f_text_data(n,wd,n,ht,n,dp)
--- else
--- break
--- end
--- end
--- end
--- return collected
--- end
-
-function metapost.textextsdata()
+function metapost.preparetextextsdata()
local textexts = top.textexts
local collected = { }
for k, data in sortedhash(top.texdata) do -- sort is nicer in trace
@@ -590,18 +531,10 @@ function metapost.textextsdata()
end
end
end
- mp.tt_initialize(collected)
+ mp.mf_tt_initialize(collected)
end
-
-metapost.intermediate = metapost.intermediate or { }
-metapost.intermediate.actions = metapost.intermediate.actions or { }
-
-metapost.method = 1 -- 1:dumb 2:clever
-
--- maybe we can latelua the texts some day
-
-local processmetapost = metapost.process
+local runmetapost = metapost.run
local function checkaskedfig(askedfig) -- return askedfig, wrappit
if not askedfig then
@@ -624,231 +557,98 @@ local function extrapass()
if trace_runs then
report_metapost("second run of job %s, asked figure %a",top.nofruns,top.askedfig)
end
- local textexts = metapost.textextsdata()
- processmetapost(top.mpx, {
- top.wrappit and do_begin_fig or "",
- no_trial_run,
- textexts and concat(textexts," ;\n") or "",
- top.initializations,
- do_safeguard,
- top.data,
- top.wrappit and do_end_fig or "",
- }, false, nil, false, true, top.askedfig)
+ metapost.preparetextextsdata()
+ runmetapost {
+ mpx = top.mpx,
+ askedfig = top.askedfig,
+ incontext = true,
+ data = {
+ top.wrappit and do_begin_fig or "",
+ no_trial_run,
+ top.initializations,
+ do_safeguard,
+ top.data,
+ top.wrappit and do_end_fig or "",
+ },
+ }
end
-function metapost.graphic_base_pass(specification) -- name will change (see mlib-ctx.lua)
- local top = startjob(true)
- --
+-- This one is called from the \TEX\ end so the specification is different
+-- from the specification to metapost,run cum suis! The definitions and
+-- extension used to be handled here but are now delegated to the format
+-- initializers because we need to accumulate them for nested instances (a
+-- side effect of going single pass).
+
+function metapost.graphic_base_pass(specification)
+ local top = startjob(true,"base")
local mpx = specification.mpx -- mandate
local data = specification.data or ""
- local definitions = specification.definitions or ""
- -- local extensions = metapost.getextensions(specification.instance,specification.useextensions)
- local extensions = specification.extensions or ""
local inclusions = specification.inclusions or ""
local initializations = specification.initializations or ""
- local askedfig = specification.figure -- no default else no wrapper
+ local askedfig,
+ wrappit = checkaskedfig(specification.figure)
+ nofruns = nofruns + 1
+ top.askedfig = askedfig
+ top.wrappit = wrappit
+ top.nofruns = nofruns
metapost.namespace = specification.namespace or ""
- --
- local askedfig, wrappit = checkaskedfig(askedfig)
- --
- nofruns = nofruns + 1
- --
- top.askedfig = askedfig
- top.wrappit = wrappit
- top.nofruns = nofruns
- --
- local done_1, done_2, done_3, forced_1, forced_2, forced_3
- if checking_enabled then
- data, done_1, forced_1 = checktexts(data)
- if extensions == "" then
- extensions, done_2, forced_2 = "", false, false
- else
- extensions, done_2, forced_2 = checktexts(extensions)
- end
- if inclusions == "" then
- inclusions, done_3, forced_3 = "", false, false
- else
- inclusions, done_3, forced_3 = checktexts(inclusions)
- end
- end
- top.intermediate = false
- top.multipass = false -- no needed here
- top.mpx = mpx
- top.data = data
- top.initializations = initializations
- local method = metapost.method
+ top.mpx = mpx
+ top.data = data
+ top.initializations = initializations
if trace_runs then
- if method == 1 then
- report_metapost("forcing two runs due to library configuration")
- elseif method ~= 2 then
- report_metapost("ignoring run due to library configuration")
- elseif not (done_1 or done_2 or done_3) then
- report_metapost("forcing one run only due to analysis")
- elseif done_1 then
- report_metapost("forcing at max two runs due to main code")
- elseif done_2 then
- report_metapost("forcing at max two runs due to extensions")
- else
- report_metapost("forcing at max two runs due to inclusions")
- end
+ report_metapost("running job %s, asked figure %a",nofruns,askedfig)
end
- if method == 1 or (method == 2 and (done_1 or done_2 or done_3)) then
- if trace_runs then
- report_metapost("first run of job %s, asked figure %a",nofruns,askedfig)
- end
- -- first true means: trialrun, second true means: avoid extra run if no multipass
- local flushed = processmetapost(mpx, {
- definitions,
- extensions,
- inclusions,
- wrappit and do_begin_fig or "",
- do_first_run,
- do_trial_run,
- initializations,
- do_safeguard,
- data,
- wrappit and do_end_fig or "",
- }, true, nil, not (forced_1 or forced_2 or forced_3), false, askedfig)
- if top.intermediate then
- for _, action in next, metapost.intermediate.actions do
- action()
- end
- end
- if not flushed or not metapost.optimize then
- -- tricky, we can only ask once for objects and therefore
- -- we really need a second run when not optimized
- -- context.MPLIBextrapass(askedfig)
- context(extrapass)
- end
- else
- if trace_runs then
- report_metapost("running job %s, asked figure %a",nofruns,askedfig)
- end
- processmetapost(mpx, {
- definitions,
- extensions,
+ runmetapost {
+ mpx = mpx,
+ askedfig = askedfig,
+ incontext = true,
+ data = {
inclusions,
wrappit and do_begin_fig or "",
- do_first_run,
- no_trial_run,
initializations,
do_safeguard,
data,
wrappit and do_end_fig or "",
- }, false, nil, false, false, askedfig)
- end
+ },
+ }
context(stopjob)
end
--- we overload metapost.process here
-
-function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, askedfig, plugmode) -- overloads
- startjob(plugmode)
- processmetapost(mpx, data, trialrun, flusher, multipass, isextrapass, askedfig)
- stopjob()
-end
-
-local start = [[\starttext]]
-local preamble = [[\def\MPLIBgraphictext#1{\startTEXpage[scale=10000]#1\stopTEXpage}]]
-local stop = [[\stoptext]]
-
-local mpyfilename = nil
-
-function makempy.registerfile(filename)
- mpyfilename = filename
+local function oldschool(mpx, data, trial_run, flusher, was_multi_pass, is_extra_pass, askedfig, incontext)
+ metapost.process {
+ mpx = mpx,
+ flusher = flusher,
+ askedfig = askedfig,
+ useplugins = incontext,
+ incontext = incontext,
+ data = data,
+ }
end
-implement {
- name = "registermpyfile",
- actions = makempy.registerfile,
- arguments = "string"
-}
-
-local pdftompy = sandbox.registerrunner {
- name = "mpy:pstoedit",
- program = "pstoedit",
- template = "-ssp -dt -f mpost %pdffile% %mpyfile%",
- checkers = {
- pdffile = "writable",
- mpyfile = "readable",
- },
- reporter = report_metapost,
-}
-
-local textopdf = sandbox.registerrunner {
- name = "mpy:context",
- program = "context",
- template = "--once %runmode% %texfile%",
- checkers = {
- runmode = "string",
- texfile = "readable",
- },
- reporter = report_metapost,
-}
-
-function makempy.processgraphics(graphics)
- if #graphics == 0 then
- return
- end
- if mpyfilename and exists(mpyfilename) then
- report_metapost("using file: %s",mpyfilename)
- return
- end
- makempy.nofconverted = makempy.nofconverted + 1
- starttiming(makempy)
- local mpofile = tex.jobname .. "-mpgraph"
- local mpyfile = file.replacesuffix(mpofile,"mpy")
- local pdffile = file.replacesuffix(mpofile,"pdf")
- local texfile = file.replacesuffix(mpofile,"tex")
- savedata(texfile, { start, preamble, metapost.tex.get(), concat(graphics,"\n"), stop }, "\n")
- textopdf {
- runmode = tex.interactionmode == 0 and "--batchmode" or "",
- texfile = texfile,
- }
- if exists(pdffile) then
- pdftompy {
- pdffile = pdffile,
- mpyfile = mpyfile,
- }
- if exists(mpyfile) then
- local result, r = { }, 0
- local data = io.loaddata(mpyfile)
- if data and #data > 0 then
- for figure in gmatch(data,"beginfig(.-)endfig") do
- r = r + 1
- result[r] = formatters["begingraphictextfig%sendgraphictextfig ;\n"](figure)
- end
- savedata(mpyfile,concat(result,""))
- end
- end
+function metapost.process(specification,...)
+ if type(specification) ~= "table" then
+ oldschool(specification,...)
+ else
+ startjob(specification.incontext or specification.useplugins,"process")
+ runmetapost(specification)
+ stopjob()
end
- stoptiming(makempy)
end
-- -- the new plugin handler -- --
-local sequencers = utilities.sequencers
-local appendgroup = sequencers.appendgroup
-local appendaction = sequencers.appendaction
+local sequencers = utilities.sequencers
+local appendgroup = sequencers.appendgroup
+local appendaction = sequencers.appendaction
-local resetter = nil
-local analyzer = nil
-local processor = nil
-
-local resetteractions = sequencers.new { arguments = "t" }
-local analyzeractions = sequencers.new { arguments = "object,prescript" }
-local processoractions = sequencers.new { arguments = "object,prescript,before,after" }
+local resetteractions = sequencers.new { arguments = "t" }
+local processoractions = sequencers.new { arguments = "object,prescript,before,after" }
appendgroup(resetteractions, "system")
-appendgroup(analyzeractions, "system")
appendgroup(processoractions,"system")
-- later entries come first
---~ local scriptsplitter = Cf(Ct("") * (
---~ Cg(C((1-S("= "))^1) * S("= ")^1 * C((1-S("\n\r"))^0) * S("\n\r")^0)
---~ )^0, rawset)
-
local scriptsplitter = Ct ( Ct (
C((1-S("= "))^1) * S("= ")^1 * C((1-S("\n\r"))^0) * S("\n\r")^0
)^0 )
@@ -857,22 +657,24 @@ local function splitprescript(script)
local hash = lpegmatch(scriptsplitter,script)
for i=#hash,1,-1 do
local h = hash[i]
-if h == "reset" then
- for k, v in next, hash do
- if type(k) ~= "number" then
- hash[k] = nil
+ if h == "reset" then
+ for k, v in next, hash do
+ if type(k) ~= "number" then
+ hash[k] = nil
+ end
+ end
+ else
+ hash[h[1]] = h[2]
end
end
-else
- hash[h[1]] = h[2]
-end
- end
if trace_scripts then
report_scripts(table.serialize(hash,"prescript"))
end
return hash
end
+metapost.splitprescript = splitprescript
+
-- -- not used:
--
-- local function splitpostscript(script)
@@ -906,27 +708,9 @@ end
function metapost.resetplugins(t) -- intialize plugins, before figure
if top.plugmode then
-
outercolormodel = colors.currentmodel() -- currently overloads the one set at the tex end
-
- -- plugins can have been added
- resetter = resetteractions.runner
- analyzer = analyzeractions.runner
- processor = processoractions.runner
- -- let's apply one runner
- resetter(t)
- end
-end
-
-function metapost.analyzeplugins(object) -- each object (first pass)
- if top.plugmode then
- local prescript = object.prescript -- specifications
- if prescript and #prescript > 0 then
- analyzer(object,splitprescript(prescript) or {})
- return top.multipass
- end
+ resetteractions.runner(t)
end
- return false
end
function metapost.processplugins(object) -- each object (second pass)
@@ -935,7 +719,7 @@ function metapost.processplugins(object) -- each object (second pass)
if prescript and #prescript > 0 then
local before = { }
local after = { }
- processor(object,splitprescript(prescript) or {},before,after)
+ processoractions.runner(object,splitprescript(prescript) or {},before,after)
return #before > 0 and before, #after > 0 and after
else
local c = object.color
@@ -954,11 +738,16 @@ local basepoints = number.dimenfactors["bp"]
local function cm(object)
local op = object.path
if op then
- local first, second, fourth = op[1], op[2], op[4]
+ local first = op[1]
+ local second = op[2]
+ local fourth = op[4]
if fourth then
- local tx, ty = first.x_coord , first.y_coord
- local sx, sy = second.x_coord - tx, fourth.y_coord - ty
- local rx, ry = second.y_coord - ty, fourth.x_coord - tx
+ local tx = first.x_coord
+ local ty = first.y_coord
+ local sx = second.x_coord - tx
+ local sy = fourth.y_coord - ty
+ local rx = second.y_coord - ty
+ local ry = fourth.x_coord - tx
if sx == 0 then sx = 0.00001 end
if sy == 0 then sy = 0.00001 end
return sx, rx, ry, sy, tx, ty
@@ -967,6 +756,8 @@ local function cm(object)
return 1, 0, 0, 1, 0, 0 -- weird case
end
+metapost.cm = cm
+
-- color
local function cl_reset(t)
@@ -975,157 +766,195 @@ end
-- text
-local function tx_reset()
- if top then
- -- why ?
- top.texhash = { }
- top.texlast = 0
+local tx_reset, tx_process do
+
+ local eol = S("\n\r")^1
+ local cleaner = Cs((P("@@")/"@" + P("@")/"%%" + P(1))^0)
+ local splitter = Ct(
+ ( (
+ P("s:") * C((1-eol)^1)
+ + P("n:") * ((1-eol)^1/tonumber)
+ + P("b:") * ((1-eol)^1/toboolean)
+ ) * eol^0 )^0)
+
+ local function applyformat(s)
+ local t = lpegmatch(splitter,s)
+ if #t == 1 then
+ return s
+ else
+ local f = lpegmatch(cleaner,t[1])
+ return formatters[f](unpack(t,2))
+ end
end
-end
-local fmt = formatters["%s %s %s % t"]
------ pat = tsplitat(":")
-local pat = lpeg.tsplitter(":",tonumber) -- so that %F can do its work
-
-local f_gray_yes = formatters["s=%F,a=%F,t=%F"]
-local f_gray_nop = formatters["s=%F"]
-local f_rgb_yes = formatters["r=%F,g=%F,b=%F,a=%F,t=%F"]
-local f_rgb_nop = formatters["r=%F,g=%F,b=%F"]
-local f_cmyk_yes = formatters["c=%F,m=%F,y=%F,k=%F,a=%F,t=%F"]
-local f_cmyk_nop = formatters["c=%F,m=%F,y=%F,k=%F"]
-
-local ctx_MPLIBsetNtext = context.MPLIBsetNtext
-local ctx_MPLIBsetCtext = context.MPLIBsetCtext
-local ctx_MPLIBsettext = context.MPLIBsettext
-
--- we reuse content when possible
--- we always create at least one instance (for dimensions)
--- we make sure we don't do that when we use one (else counter issues with e.g. \definelabel)
-
-local eol = S("\n\r")^1
-local cleaner = Cs((P("@@")/"@" + P("@")/"%%" + P(1))^0)
-local splitter = Ct(
- ( (
- P("s:") * C((1-eol)^1)
- + P("n:") * ((1-eol)^1/tonumber)
- + P("b:") * ((1-eol)^1/toboolean)
- ) * eol^0 )^0)
-
-local function applyformat(s)
- local t = lpegmatch(splitter,s)
- if #t == 1 then
- return s
- else
- local f = lpegmatch(cleaner,t[1])
- return formatters[f](unpack(t,2))
- end
-end
-
-local function tx_analyze(object,prescript)
- local data = top.texdata[metapost.properties.number]
- local tx_stage = prescript.tx_stage
- if tx_stage == "trial" then
- local tx_trial = data.textrial + 1
- data.textrial = tx_trial
- local tx_number = tonumber(prescript.tx_number)
- local s = object.postscript or ""
- local c = object.color -- only simple ones, no transparency
- if #c == 0 then
- local txc = prescript.tx_color
- if txc then
- c = lpegmatch(pat,txc)
+ local fmt = formatters["%s %s %s % t"]
+ ----- pat = tsplitat(":")
+ local pat = lpeg.tsplitter(":",tonumber) -- so that %F can do its work
+
+ local f_gray_yes = formatters["s=%.3F,a=%i,t=%.3F"]
+ local f_gray_nop = formatters["s=%.3F"]
+ local f_rgb_yes = formatters["r=%.3F,g=%.3F,b=%.3F,a=%.3F,t=%.3F"]
+ local f_rgb_nop = formatters["r=%.3F,g=%.3F,b=%.3F"]
+ local f_cmyk_yes = formatters["c=%.3F,m=%.3F,y=%.3F,k=%.3F,a=%.3F,t=%.3F"]
+ local f_cmyk_nop = formatters["c=%.3F,m=%.3F,y=%.3F,k=%.3F"]
+
+ directives.register("metapost.stripzeros",function()
+ f_gray_yes = formatters["s=%.3N,a=%i,t=%.3N"]
+ f_gray_nop = formatters["s=%.3N"]
+ f_rgb_yes = formatters["r=%.3N,g=%.3N,b=%.3N,a=%.3N,t=%.3N"]
+ f_rgb_nop = formatters["r=%.3N,g=%.3N,b=%.3N"]
+ f_cmyk_yes = formatters["c=%.3N,m=%.3N,y=%.3N,k=%.3N,a=%.3N,t=%.3N"]
+ f_cmyk_nop = formatters["c=%.3N,m=%.3N,y=%.3N,k=%.3N"]
+ end)
+
+ local ctx_MPLIBsetNtext = context.MPLIBsetNtextX
+ local ctx_MPLIBsetCtext = context.MPLIBsetCtextX
+ local ctx_MPLIBsettext = context.MPLIBsettextX
+
+ local bp = number.dimenfactors.bp
+
+ local mp_index = 0
+ local mp_target = 0
+ local mp_c = nil
+ local mp_a = nil
+ local mp_t = nil
+
+ local function processtext()
+ local mp_text = top.texstrings[mp_index]
+ if not mp_text then
+ report_textexts("missing text for index %a",mp_index)
+ elseif not mp_c then
+ ctx_MPLIBsetNtext(mp_target,mp_text)
+ elseif #mp_c == 1 then
+ if mp_a and mp_t then
+ ctx_MPLIBsetCtext(mp_target,f_gray_yes(mp_c[1],mp_a,mp_t),mp_text)
+ else
+ ctx_MPLIBsetCtext(mp_target,f_gray_nop(mp_c[1]),mp_text)
end
- end
- if prescript.tx_type == "format" then
- s = applyformat(s)
- end
- local a = tonumber(prescript.tr_alternative)
- local t = tonumber(prescript.tr_transparency)
- local h = fmt(tx_number,a or "-",t or "-",c or "-")
- local n = data.texhash[h] -- todo: hashed variant with s (nicer for similar labels)
- if n then
- data.texslots[tx_trial] = n
- if trace_textexts then
- report_textexts("stage %a, usage %a, number %a, %s %a, hash %a, text %a",tx_stage,tx_trial,tx_number,"old",n,h,s)
+ elseif #mp_c == 3 then
+ if mp_a and mp_t then
+ ctx_MPLIBsetCtext(mp_target,f_rgb_nop(mp_c[1],mp_c[2],mp_c[3],mp_a,mp_t),mp_text)
+ else
+ ctx_MPLIBsetCtext(mp_target,f_rgb_nop(mp_c[1],mp_c[2],mp_c[3]),mp_text)
end
- elseif prescript.tx_global == "yes" and data.texorder[tx_number] then
- -- we already have one flush and don't want it redone .. this needs checking
- if trace_textexts then
- report_textexts("stage %a, usage %a, number %a, %s %a, hash %a, text %a",tx_stage,tx_trial,tx_number,"ignored",tx_last,h,s)
+ elseif #mp_c == 4 then
+ if mp_a and mp_t then
+ ctx_MPLIBsetCtext(mp_target,f_cmyk_yes(mp_c[1],mp_c[2],mp_c[3],mp_c[4],mp_a,mp_t),mp_text)
+ else
+ ctx_MPLIBsetCtext(mp_target,f_cmyk_nop(mp_c[1],mp_c[2],mp_c[3],mp_c[4]),mp_text)
end
else
- local tx_last = top.texlast + 1
- top.texlast = tx_last
- -- report_textexts("tex string: %s",s)
- if not c then
- ctx_MPLIBsetNtext(tx_last,s)
- elseif #c == 1 then
- if a and t then
- ctx_MPLIBsetCtext(tx_last,f_gray_yes(c[1],a,t),s)
- else
- ctx_MPLIBsetCtext(tx_last,f_gray_nop(c[1]),s)
- end
- elseif #c == 3 then
- if a and t then
- ctx_MPLIBsetCtext(tx_last,f_rgb_nop(c[1],c[2],c[3],a,t),s)
- else
- ctx_MPLIBsetCtext(tx_last,f_rgb_nop(c[1],c[2],c[3]),s)
- end
- elseif #c == 4 then
- if a and t then
- ctx_MPLIBsetCtext(tx_last,f_cmyk_yes(c[1],c[2],c[3],c[4],a,t),s)
- else
- ctx_MPLIBsetCtext(tx_last,f_cmyk_nop(c[1],c[2],c[3],c[4]),s)
- end
- else
- ctx_MPLIBsetNtext(tx_last,s)
+ -- can't happen
+ ctx_MPLIBsetNtext(mp_target,mp_text)
+ end
+ end
+
+ function mp.mf_some_text(index,str)
+ mp_target = index
+ mp_index = index
+ mp_c = nil
+ mp_a = nil
+ mp_t = nil
+ top.texstrings[mp_index] = str
+ tex.runtoks("mptexttoks")
+ local box = textakebox("mptextbox")
+ top.textexts[mp_target] = box
+ mp.triplet(bp*box.width,bp*box.height,bp*box.depth)
+ madetext = nil
+ end
+
+ local madetext = nil
+
+ function mp.mf_made_text(index)
+ mp.mf_some_text(index,madetext)
+ end
+
+ function metapost.maketext(s,mode)
+ if mode and mode == 1 then
+ if trace_btexetex then
+ report_metapost("ignoring verbatimtex: [[%s]]",s)
end
- top.multipass = true
- data.texhash [h] = tx_last
- -- data.texhash [tx_number] = tx_last
- data.texslots[tx_trial] = tx_last
- data.texorder[tx_number] = tx_last
- if trace_textexts then
- report_textexts("stage %a, usage %a, number %a, %s %a, hash %a, text %a",tx_stage,tx_trial,tx_number,"new",tx_last,h,s)
+ else
+ if trace_btexetex then
+ report_metapost("handling btex ... etex: [[%s]]",s)
end
+ -- madetext = utilities.strings.collapse(s)
+ madetext = s
+ return "rawmadetext"
end
- elseif tx_stage == "extra" then
- local tx_trial = data.textrial + 1
- data.textrial = tx_trial
- local tx_number = tonumber(prescript.tx_number)
- if not data.texorder[tx_number] then
- local s = object.postscript or ""
- local tx_last = top.texlast + 1
- top.texlast = tx_last
- ctx_MPLIBsettext(tx_last,s)
- top.multipass = true
- data.texslots[tx_trial] = tx_last
- data.texorder[tx_number] = tx_last
- if trace_textexts then
- report_textexts("stage %a, usage %a, number %a, extra %a, text %a",tx_stage,tx_trial,tx_number,tx_last,s)
+ end
+
+ function mp.mf_formatted_text(index,fmt,...)
+ local t = { }
+ for i=1,select("#",...) do
+ local ti = select(i,...)
+ if type(ti) ~= "table" then
+ t[#t+1] = ti
end
end
+ local f = lpegmatch(cleaner,fmt)
+ local s = formatters[f](unpack(t)) or ""
+ mp.mf_some_text(index,s)
end
-end
-local function tx_process(object,prescript,before,after)
- local data = top.texdata[metapost.properties.number]
- local tx_number = tonumber(prescript.tx_number)
- if tx_number then
- local tx_stage = prescript.tx_stage
- if tx_stage == "final" then
- local tx_final = data.texfinal + 1
- data.texfinal = tx_final
- local n = data.texslots[tx_final]
+ interfaces.implement {
+ name = "mptexttoks",
+ actions = processtext,
+ }
+
+ tx_reset = function()
+ if top then
+ top.texhash = { }
+ top.texlast = 0
+ end
+ end
+
+ tx_process = function(object,prescript,before,after)
+ local data = top.texdata[metapost.properties.number]
+ local index = tonumber(prescript.tx_index)
+ if index then
if trace_textexts then
- report_textexts("stage %a, usage %a, number %a, use %a",tx_stage,tx_final,tx_number,n)
+ report_textexts("using index %a",index)
+ end
+ --
+ mp_c = object.color
+ if #mp_c == 0 then
+ local txc = prescript.tx_color
+ if txc then
+ mp_c = lpegmatch(pat,txc)
+ end
+ end
+ mp_a = tonumber(prescript.tr_alternative)
+ mp_t = tonumber(prescript.tr_transparency)
+ --
+ mp_index = index
+ mp_target = top.texlast - 1
+ top.texlast = mp_target
+ --
+ local mp_text = top.texstrings[mp_index]
+ local box
+ if prescript.tx_cache == "no" then
+ tex.runtoks("mptexttoks")
+ box = textakebox("mptextbox")
+ else
+ local hash = fmt(mp_text,mp_a or "-",mp_t or "-",mp_c or "-")
+ box = data.texhash[hash]
+ if box then
+ box = copy_list(box)
+ else
+ tex.runtoks("mptexttoks")
+ box = textakebox("mptextbox")
+ data.texhash[hash] = box
+ end
end
- local sx, rx, ry, sy, tx, ty = cm(object) -- needs to be frozen outside the function
- local box = top.textexts[n]
+ top.textexts[mp_target] = box
+ --
if box then
+ -- we need to freeze the variables outside the function
+ local sx, rx, ry, sy, tx, ty = cm(object)
+ local target = mp_target
before[#before+1] = function()
- -- flush always happens, we can have a special flush function injected before
- context.MPLIBgettextscaledcm(n,
+ context.MPLIBgettextscaledcm(target,
f_f(sx), -- bah ... %s no longer checks
f_f(rx), -- bah ... %s no longer checks
f_f(ry), -- bah ... %s no longer checks
@@ -1136,7 +965,7 @@ local function tx_process(object,prescript,before,after)
end
else
before[#before+1] = function()
- report_textexts("unknown %s",tx_number)
+ report_textexts("unknown %s",index)
end
end
if not trace_textexts then
@@ -1147,6 +976,7 @@ local function tx_process(object,prescript,before,after)
object.istext = true
end
end
+
end
-- we could probably redo normal textexts in the next way but as it's rather optimized
@@ -1182,30 +1012,31 @@ end
-- graphics (we use the given index because pictures can be reused)
-local graphics = { }
-function metapost.intermediate.actions.makempy()
- if #graphics > 0 then
- makempy.processgraphics(graphics)
- graphics = { } -- ? could be gt_reset
- end
-end
+local gt_reset, gt_process do
+
+ local graphics = { }
-local function gt_analyze(object,prescript)
- local gt_stage = prescript.gt_stage
- local gt_index = tonumber(prescript.gt_index)
- if gt_stage == "trial" and not graphics[gt_index] then
- graphics[gt_index] = formatters["\\MPLIBgraphictext{%s}"](object.postscript or "")
- top.intermediate = true
- top.multipass = true
+
+ local mp_index = 0
+ local mp_str = ""
+
+ function mp.mf_graphic_text(index,str)
+ if not graphics[index] then
+ mp_index = index
+ mp_str = str
+ tex.runtoks("mpgraphictexttoks")
+ end
end
-end
--- local function gt_process(object,prescript,before,after)
--- local gt_stage = prescript.gt_stage
--- if gt_stage == "final" then
--- end
--- end
+ interfaces.implement {
+ name = "mpgraphictexttoks",
+ actions = function()
+ context.MPLIBgraphictext(mp_index,mp_str)
+ end,
+ }
+
+end
-- shades
@@ -1342,7 +1173,7 @@ end
local function bm_process(object,prescript,before,after)
local bm_xresolution = prescript.bm_xresolution
if bm_xresolution then
- before[#before+1] = f_cm(cm(object))
+ before[#before+1] = f_cm_b(cm(object))
before[#before+1] = function()
figures.bitmapimage {
xresolution = tonumber(bm_xresolution),
@@ -1352,7 +1183,7 @@ local function bm_process(object,prescript,before,after)
data = object.postscript
}
end
- before[#before+1] = "Q"
+ before[#before+1] = s_cm_e
object.path = false
object.color = false
object.grouped = true
@@ -1364,10 +1195,13 @@ end
local function ps_process(object,prescript,before,after)
local ps_label = prescript.ps_label
if ps_label then
- local op = object.path
- local first, third = op[1], op[3]
- local x, y = first.x_coord, first.y_coord
- local w, h = third.x_coord - x, third.y_coord - y
+ local op = object.path
+ local first = op[1]
+ local third = op[3]
+ local x = first.x_coord
+ local y = first.y_coord
+ local w = third.x_coord - x
+ local h = third.y_coord - y
local properties = metapost.properties
x = x - properties.llx
y = properties.ury - y
@@ -1380,14 +1214,33 @@ end
-- figures
+-- local sx, rx, ry, sy, tx, ty = cm(object)
+-- sxsy(box.width,box.height,box.depth))
+
+function mp.mf_external_figure(filename)
+ local f = figures.getinfo(filename)
+ local w = 0
+ local h = 0
+ if f then
+ local u = f.used
+ if u and u.fullname then
+ w = u.width or 0
+ h = u.height or 0
+ end
+ else
+ report_metapost("external figure %a not found",filename)
+ end
+ mp.triplet(w/65536,h/65536,0)
+end
+
local function fg_process(object,prescript,before,after)
local fg_name = prescript.fg_name
if fg_name then
- before[#before+1] = f_cm(cm(object)) -- beware: does not use the cm stack
+ before[#before+1] = f_cm_b(cm(object)) -- beware: does not use the cm stack
before[#before+1] = function()
context.MPLIBfigure(fg_name,prescript.fg_mask or "")
end
- before[#before+1] = "Q"
+ before[#before+1] = s_cm_e
object.path = false
object.grouped = true
end
@@ -1411,14 +1264,27 @@ local remappers = {
[4] = formatters["c=%s,m=%s,y=%s,k=%s"],
}
+local processlast = 0
+local processhash = setmetatableindex(function(t,k)
+ processlast = processlast + 1
+ local v = formatters["mp_%s"](processlast)
+ defineprocesscolor(v,k,true,true)
+ t[k] = v
+ return v
+end)
+
+local function checked_transparency(alternative,transparency,before,after)
+ alternative = tonumber(alternative) or 1
+ transparency = tonumber(transparency) or 0
+ before[#before+1] = formatters["/Tr%s gs"](registertransparency(nil,alternative,transparency,true))
+ after [#after +1] = "/Tr0 gs" -- outertransparency
+end
+
local function tr_process(object,prescript,before,after)
-- before can be shortcut to t
local tr_alternative = prescript.tr_alternative
if tr_alternative then
- tr_alternative = tonumber(tr_alternative)
- local tr_transparency = tonumber(prescript.tr_transparency)
- before[#before+1] = formatters["/Tr%s gs"](registertransparency(nil,tr_alternative,tr_transparency,true))
- after[#after+1] = "/Tr0 gs" -- outertransparency
+ checked_transparency(tr_alternative,prescript.tr_transparency,before,after)
end
local cs = object.color
if cs and #cs > 0 then
@@ -1429,29 +1295,35 @@ local function tr_process(object,prescript,before,after)
else
local sp_name = prescript.sp_name or "black"
if sp_type == "spot" then
- local sp_value = prescript.sp_value or "s:1"
- local sp_temp = formatters["mp:%s"](sp_value)
- local s = split(sp_value,":")
- local r = remappers[#s]
- defineprocesscolor(sp_temp,r and r(unpack(s)) or "s=0",true,true)
- definespotcolor(sp_name,sp_temp,"p=1",true)
+ local sp_value = prescript.sp_value or "1"
+ local components = split(sp_value,":")
+ local specification = remappers[#components]
+ if specification then
+ specification = specification(unpack(components))
+ else
+ specification = "s=0"
+ end
+ local sp_spec = processhash[specification]
+ definespotcolor(sp_name,sp_spec,"p=1",true)
sp_type = "named"
elseif sp_type == "multitone" then -- (fractions of a multitone) don't work well in mupdf
- local sp_value = prescript.sp_value or "s:1"
- local sp_spec = { }
+ local sp_value = prescript.sp_value or "1"
+ local sp_specs = { }
local sp_list = split(sp_value," ")
for i=1,#sp_list do
- local v = sp_list[i]
- local t = formatters["mp:%s"](v)
- local s = split(v,":")
- local r = remappers[#s]
- defineprocesscolor(t,r and r(unpack(s)) or "s=0",true,true)
- local tt = formatters["ms:%s"](v)
- definespotcolor(tt,t,"p=1",true)
- sp_spec[#sp_spec+1] = formatters["%s=1"](t)
+ local sp_value = sp_list[i]
+ local components = split(sp_value,":")
+ local specification = remappers[#components]
+ if specification then
+ specification = specification(unpack(components))
+ else
+ specification = "s=0"
+ end
+ local sp_spec = processhash[specification]
+ sp_specs[i] = formatters["%s=1"](sp_spec)
end
- sp_spec = concat(sp_spec,",")
- definemultitonecolor(sp_name,sp_spec,"","",true)
+ sp_specs = concat(sp_specs,",")
+ definemultitonecolor(sp_name,sp_specs,"","")
sp_type = "named"
end
if sp_type == "named" then
@@ -1463,8 +1335,7 @@ local function tr_process(object,prescript,before,after)
local t = t_list[sp_name] -- string or attribute
local v = t and transparencyvalue(t)
if v then
- before[#before+1] = formatters["/Tr%s gs"](registertransparency(nil,v[1],v[2],true))
- after[#after+1] = "/Tr0 gs" -- outertransparency
+ checked_transparency(v[1],v[2],before,after)
end
end
local c = c_list[sp_name] -- string or attribute
@@ -1472,29 +1343,34 @@ local function tr_process(object,prescript,before,after)
if v then
-- all=1 gray=2 rgb=3 cmyk=4
local colorspace = v[1]
- local f = cs[1]
+ local factor = cs[1]
if colorspace == 2 then
- local s = f*v[2]
+ local s = factor * v[2]
c_b, c_a = checked_color_pair(f_gray,s,s)
elseif colorspace == 3 then
- local r, g, b = f*v[3], f*v[4], f*v[5]
+ local r = factor * v[3]
+ local g = factor * v[4]
+ local b = factor * v[5]
c_b, c_a = checked_color_pair(f_rgb,r,g,b,r,g,b)
elseif colorspace == 4 or colorspace == 1 then
- local c, m, y, k = f*v[6], f*v[7], f*v[8], f*v[9]
+ local c = factor * v[6]
+ local m = factor * v[7]
+ local y = factor * v[8]
+ local k = factor * v[9]
c_b, c_a = checked_color_pair(f_cmyk,c,m,y,k,c,m,y,k)
elseif colorspace == 5 then
-- not all viewers show the fractions ok
local name = v[10]
local value = split(v[13],",")
- if f ~= 1 then
+ if factor ~= 1 then
for i=1,#value do
- value[i] = f * (tonumber(value[i]) or 1)
+ value[i] = f_scn(factor * (tonumber(value[i]) or 1))
end
end
value = concat(value," ")
c_b, c_a = checked_color_pair(f_spot,name,name,value,value)
else
- local s = f*v[2]
+ local s = factor *v[2]
c_b, c_a = checked_color_pair(f_gray,s,s)
end
end
@@ -1519,10 +1395,6 @@ end
-- groups
-local types = {
- isolated
-}
-
local function gr_process(object,prescript,before,after)
local gr_state = prescript.gr_state
if not gr_state then
@@ -1530,7 +1402,10 @@ local function gr_process(object,prescript,before,after)
elseif gr_state == "start" then
local gr_type = utilities.parsers.settings_to_set(prescript.gr_type)
local path = object.path
- local p1, p2, p3, p4 = path[1], path[2], path[3], path[4]
+ local p1 = path[1]
+ local p2 = path[2]
+ local p3 = path[3]
+ local p4 = path[4]
local llx = min(p1.x_coord,p2.x_coord,p3.x_coord,p4.x_coord)
local lly = min(p1.y_coord,p2.y_coord,p3.y_coord,p4.y_coord)
local urx = max(p1.x_coord,p2.x_coord,p3.x_coord,p4.x_coord)
@@ -1554,82 +1429,88 @@ end
-- outlines
-local outlinetexts = { }
+local ot_reset, ot_process do
-local function ot_reset()
- outlinetexts = { }
-end
+ local outlinetexts = { } -- also in top data
-local function ot_analyze(object,prescript)
- local ot_stage = prescript.ot_stage
- local ot_index = tonumber(prescript.ot_index)
- if ot_index and ot_stage == "trial" and not outlinetexts[ot_index] then
- local ot_kind = prescript.ot_kind or ""
- top.intermediate = true
- top.multipass = true
- context.MPLIBoutlinetext(ot_index,ot_kind,object.postscript)
+ ot_reset = function ()
+ outlinetexts = { }
end
-end
-local function ot_process(object,prescript,before,after)
-end
+ local mp_index = 0
+ local mp_kind = ""
+ local mp_str = ""
-implement {
- name = "MPLIBconvertoutlinetext",
- arguments = { "integer", "string", "integer" },
- actions = function(index,kind,box)
- local boxtomp = fonts.metapost.boxtomp
- if boxtomp then
- outlinetexts[index] = boxtomp(box,kind)
- else
- outlinetexts[index] = ""
+ function mp.mf_outline_text(index,str,kind)
+ if not outlinetexts[index] then
+ mp_index = index
+ mp_kind = kind
+ mp_str = str
+ tex.runtoks("mpoutlinetoks")
end
end
-}
-function mp.get_outline_text(index) -- maybe we need a more private namespace
- mp.print(outlinetexts[index] or "draw origin;")
-end
+ interfaces.implement {
+ name = "mpoutlinetoks",
+ actions = function()
+ context.MPLIBoutlinetext(mp_index,mp_kind,mp_str)
+ end,
+ }
+ implement {
+ name = "MPLIBconvertoutlinetext",
+ arguments = { "integer", "string", "integer" },
+ actions = function(index,kind,box)
+ local boxtomp = fonts.metapost.boxtomp
+ if boxtomp then
+ outlinetexts[index] = boxtomp(box,kind)
+ else
+ outlinetexts[index] = ""
+ end
+ end
+ }
--- definitions
+ function mp.mf_get_outline_text(index) -- maybe we need a more private namespace
+ mp.print(outlinetexts[index] or "draw origin;")
+ end
-appendaction(resetteractions, "system",ot_reset)
-appendaction(resetteractions, "system",cl_reset)
-appendaction(resetteractions, "system",tx_reset)
+end
-appendaction(processoractions,"system",ot_process)
-appendaction(processoractions,"system",gr_process)
+-- mf_object=<string>
-appendaction(analyzeractions, "system",ot_analyze)
-appendaction(analyzeractions, "system",tx_analyze)
-appendaction(analyzeractions, "system",gt_analyze)
+local p1 = P("mf_object=")
+local p2 = lpeg.patterns.eol * p1
+local pattern = (1-p2)^0 * p2 + p1
-appendaction(processoractions,"system",sh_process)
--- (processoractions,"system",gt_process)
-appendaction(processoractions,"system",bm_process)
-appendaction(processoractions,"system",tx_process)
-appendaction(processoractions,"system",bx_process)
-appendaction(processoractions,"system",ps_process)
-appendaction(processoractions,"system",fg_process)
-appendaction(processoractions,"system",tr_process) -- last, as color can be reset
+function metapost.isobject(str)
+ return pattern and str ~= "" and lpegmatch(p,str) and true or false
+end
-appendaction(processoractions,"system",la_process)
+local function installplugin(specification)
+ local reset = specification.reset
+ local process = specification.process
+ local object = specification.object
+ if reset then
+ appendaction(resetteractions,"system",reset)
+ end
+ if process then
+ appendaction(processoractions,"system",process)
+ end
+end
--- function metapost.installplugin(reset,analyze,process)
--- if reset then
--- appendaction(resetteractions,"system",reset)
--- end
--- if analyze then
--- appendaction(analyzeractions,"system",analyze)
--- end
--- if process then
--- appendaction(processoractions,"system",process)
--- end
--- end
+metapost.installplugin = installplugin
--- we're nice and set them already
+-- definitions
-resetter = resetteractions .runner
-analyzer = analyzeractions .runner
-processor = processoractions.runner
+installplugin { name = "outline", reset = ot_reset, process = ot_process }
+installplugin { name = "color", reset = cl_reset, process = cl_process }
+installplugin { name = "text", reset = tx_reset, process = tx_process }
+installplugin { name = "group", reset = gr_reset, process = gr_process }
+installplugin { name = "graphictext", reset = gt_reset, process = gt_process }
+installplugin { name = "shade", reset = sh_reset, process = sh_process }
+installplugin { name = "bitmap", reset = bm_reset, process = bm_process }
+installplugin { name = "box", reset = bx_reset, process = bx_process }
+installplugin { name = "position", reset = ps_reset, process = ps_process }
+installplugin { name = "figure", reset = fg_reset, process = fg_process }
+installplugin { name = "layer", reset = la_reset, process = la_process }
+installplugin { name = "transparency", reset = tr_reset, process = tr_process }
diff --git a/tex/context/base/mkiv/mlib-pps.mkiv b/tex/context/base/mkiv/mlib-pps.mkiv
index c9d181bf9..051130585 100644
--- a/tex/context/base/mkiv/mlib-pps.mkiv
+++ b/tex/context/base/mkiv/mlib-pps.mkiv
@@ -57,14 +57,36 @@
\let\MPLIBsettext\MPLIBsetNtext
+\unexpanded\def\MPLIBsetNtextX#1% #2% box text
+ {\MPLIBflushenvironment
+ \hbox\bgroup % text
+ \meta_set_current_color
+ \let\MPLIBflushenvironment\doMPLIBflushenvironment
+ \let\next}
+
+\unexpanded\def\MPLIBsetCtextX#1#2% #3% box colorspec text
+ {\MPLIBflushenvironment
+ \hbox\bgroup % text
+ \directcolored[#2]%
+ \meta_set_current_color % so, textcolor wins !
+ \let\MPLIBflushenvironment\doMPLIBflushenvironment
+ \let\next}
+
+\let\MPLIBsettextX\MPLIBsetNtextX
+
\unexpanded\def\MPLIBgettextscaled#1#2#3% why a copy .. can be used more often
{\clf_mpgettext\MPtextbox #1%
\vpack to \zeropoint{\vss\hpack to \zeropoint{\scale[\c!sx=#2,\c!sy=#3]{\raise\dp\MPtextbox\box\MPtextbox}\forcecolorhack\hss}}}
+% \unexpanded\def\MPLIBfigure#1#2%
+% {\setbox\scratchbox\hpack{\externalfigure[#1][\c!mask=#2]}%
+% \clf_mpsetsxsy\wd\scratchbox\ht\scratchbox\zeropoint
+% \vpack to \zeropoint{\vss\hpack to \zeropoint{\scale[\c!sx=\sx,\c!sy=\sy]{\box\scratchbox}\hss}}}
+
\unexpanded\def\MPLIBfigure#1#2%
{\setbox\scratchbox\hpack{\externalfigure[#1][\c!mask=#2]}%
\clf_mpsetsxsy\wd\scratchbox\ht\scratchbox\zeropoint
- \vpack to \zeropoint{\vss\hpack to \zeropoint{\scale[\c!sx=\sx,\c!sy=\sy]{\box\scratchbox}\hss}}}
+ \vpack to \zeropoint{\vss\hpack to \zeropoint{\fastsxsy{\sx}{\sy}{\box\scratchbox}\hss}}}
% horrible (we could inline scale and matrix code):
@@ -185,4 +207,15 @@
\setbox\scratchbox\hpack\bgroup
\unexpanded\def\MPLIBstopgroup{\doMPLIBstopgroup{#1}{#2}{#3}{#4}{#5}{#6}}}
+% For now here ... will be cleaned up:
+
+\newtoks\mptexttoks
+\newbox \mptextbox
+\newtoks\mpoutlinetoks
+\newtoks\mpgraphictexttoks
+
+\mptexttoks {\global\setbox\mptextbox\hbox{\clf_mptexttoks}}
+\mpoutlinetoks {\global\setbox\mptextbox\vbox{\clf_mpoutlinetoks}}
+\mpgraphictexttoks{\global\setbox\mptextbox\vbox{\clf_mpgraphictexttoks}}
+
\protect \endinput
diff --git a/tex/context/base/mkiv/mlib-run.lua b/tex/context/base/mkiv/mlib-run.lua
index 18bc7e4da..670c0e16b 100644
--- a/tex/context/base/mkiv/mlib-run.lua
+++ b/tex/context/base/mkiv/mlib-run.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['mlib-run'] = {
license = "see context related readme files",
}
+-- todo mpx :execute -> mlib.execute(mpx,)
+
-- cmyk -> done, native
-- spot -> done, but needs reworking (simpler)
-- multitone ->
@@ -30,7 +32,6 @@ nears zero.</p>
--ldx]]--
local type, tostring, tonumber, next = type, tostring, tonumber, next
-local gsub, match, find = string.gsub, string.match, string.find
local striplines = utilities.strings.striplines
local concat, insert, remove = table.concat, table.insert, table.remove
@@ -70,20 +71,6 @@ end
----- 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)
--
@@ -97,21 +84,6 @@ do
local new_instance = mplib.new
- 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)
- return temp
- end
- end
- return name
- end
-
- mplib.preprocessed = preprocessed -- helper
-
local function validftype(ftype)
if ftype == "" then
-- whatever
@@ -123,14 +95,13 @@ do
end
finders.file = function(specification,name,mode,ftype)
- return preprocessed(resolvers.findfile(name,validftype(ftype)))
+ return resolvers.findfile(name,validftype(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
local found = finder(specification,name,mode,validftype(ftype))
- -- print(found)
return found
end
@@ -160,7 +131,9 @@ function metapost.reporterror(result)
if not result then
report_metapost("error: no result object returned")
elseif result.status > 0 then
- local t, e, l = result.term, result.error, result.log
+ local t = result.term
+ local e = result.error
+ local l = result.log
local report = metapost.texerrors and texerrormessage or report_metapost
if t and t ~= "" then
report("mp error: %s",striplines(t))
@@ -193,7 +166,8 @@ local f_preamble = formatters [ [[
local methods = {
double = "double",
scaled = "scaled",
- binary = "binary",
+ -- binary = "binary",
+ binary = "double",
decimal = "decimal",
default = "scaled",
}
@@ -208,18 +182,6 @@ end
-- todo: random_seed
-local f_textext = formatters[ [[rawtextext("%s")]] ]
-
-function metapost.maketext(s,mode)
- if mode and mode == 1 then
- -- report_metapost("ignoring verbatimtex: %s",s)
- else
- -- report_metapost("handling btex ... etex: %s",s)
- s = gsub(s,'"','"&ditto&"')
- return f_textext(s)
- end
-end
-
local seed = nil
function metapost.load(name,method)
@@ -291,24 +253,103 @@ function metapost.unload(mpx)
stoptiming(mplib)
end
-local mpxformats = { }
+-- The flatten hack is needed because the library currently barks on \n\n and the
+-- collapse because mp cannot handle snippets due to grouping issues.
+
+local function flatten(source,target)
+ for i=1,#source do
+ local d = source[i]
+ if type(d) == "table" then
+ flatten(d,target)
+ elseif d and d ~= "" then
+ target[#target+1] = d
+ end
+ end
+ return target
+end
+
+local function prepareddata(data,collapse)
+ if data and data ~= "" then
+ if type(data) == "table" then
+ data = flatten(data,{ })
+ if collapse then
+ data = #data > 1 and concat(data,"\n") or data[1]
+ end
+ end
+ return data
+ end
+end
+
+metapost.defaultformat = "metafun"
+metapost.defaultinstance = "metafun"
+metapost.defaultmethod = "default"
-function metapost.format(instance,name,method)
+local mpxformats = { }
+local nofformats = 0
+local mpxpreambles = { }
+
+function metapost.pushformat(specification,f,m) -- was: instance, name, method
+ if type(specification) ~= "table" then
+ specification = {
+ instance = specification,
+ format = f,
+ method = m,
+ }
+ end
+ local instance = specification.instance
+ local format = specification.format
+ local method = specification.method
+ local definitions = specification.definitions
+ local extensions = specification.extensions
+ local preamble = nil
if not instance or instance == "" then
- instance = "metafun" -- brrr
+ instance = metapost.defaultinstance
+ specification.instance = instance
+ end
+ if not format or format == "" then
+ format = metapost.defaultformat
+ specification.format = format
+ end
+ if not method or method == "" then
+ method = metapost.defaultmethod
+ specification.method = method
+ end
+ if definitions and definitions ~= "" then
+ preamble = definitions
+ end
+ if extensions and extensions ~= "" then
+ if preamble then
+ preamble = preamble .. "\n" .. extensions
+ else
+ preamble = extensions
+ end
+ end
+ nofformats = nofformats + 1
+ local usedinstance = instance .. ":" .. nofformats
+ local mpx = mpxformats[usedinstance]
+ local mpp = mpxpreambles[instance] or ""
+ if preamble then
+ preamble = prepareddata(preamble,true)
+ mpp = mpp .. "\n" .. preamble
+ mpxpreambles[instance] = mpp
end
- name = name or instance
- local mpx = mpxformats[instance]
if not mpx then
- report_metapost("initializing instance %a using format %a",instance,name)
- mpx = metapost.checkformat(name,method)
- mpxformats[instance] = mpx
+ report_metapost("initializing instance %a using format %a and method %a",usedinstance,format,method)
+ mpx = metapost.checkformat(format,method)
+ mpxformats[usedinstance] = mpx
+ if mpp ~= "" then
+ preamble = mpp
+ end
+ end
+ if preamble then
+ mpx:execute(preamble)
end
+ specification.mpx = mpx
return mpx
end
-function metapost.instance(instance)
- return mpxformats[instance]
+function metapost.popformat()
+ nofformats = nofformats - 1
end
function metapost.reset(mpx)
@@ -335,10 +376,6 @@ local mp_tag = 0
-- key/values
-if not metapost.initializescriptrunner then
- function metapost.initializescriptrunner() end
-end
-
do
local stack, top = { }, nil
@@ -379,16 +416,47 @@ do
end
-function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, askedfig)
- local converted, result = false, { }
- if type(mpx) == "string" then
- mpx = metapost.format(mpx) -- goody
+
+if not metapost.process then
+
+ function metapost.process(specification)
+ metapost.run(specification)
+ end
+
+end
+
+-- run, process, convert and flush all work with a specification with the
+-- following (often optional) fields
+--
+-- mpx string or mp object
+-- data string or table of strings
+-- flusher table with flush methods
+-- askedfig string ("all" etc) or number
+-- incontext boolean
+-- plugmode boolean
+
+local function makebeginbanner(specification)
+ return formatters["%% begin graphic: n=%s\n\n"](metapost.n)
+end
+
+local function makeendbanner(specification)
+ return "\n% end graphic\n\n"
+end
+
+function metapost.run(specification)
+ local mpx = specification.mpx
+ local data = specification.data
+ local converted = false
+ local result = { }
+ local mpxdone = type(mpx) == "string"
+ if mpxdone then
+ mpx = metapost.pushformat { instance = mpx, format = mpx }
end
if mpx and data then
local tra = nil
starttiming(metapost)
- metapost.variables = { }
- metapost.initializescriptrunner(mpx,trialrun)
+ metapost.variables = { } -- todo also push / pop
+ metapost.pushscriptrunner(mpx)
if trace_graphics then
tra = mp_tra[mpx]
if not tra then
@@ -400,39 +468,12 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass,
}
mp_tra[mpx] = tra
end
- local banner = formatters["%% begin graphic: n=%s, trialrun=%s, multipass=%s, isextrapass=%s\n\n"](
- metapost.n, tostring(trialrun), tostring(multipass), tostring(isextrapass))
+ local banner = makebeginbanner(specification)
tra.inp:write(banner)
tra.log:write(banner)
end
- if type(data) == "table" then
- -- this hack is needed because the library currently barks on \n\n
- -- eventually we can text for "" in the next loop
- local n = 0
- local nofsnippets = #data
- for i=1,nofsnippets do
- local d = data[i]
- if d ~= "" then
- n = n + 1
- data[n] = d
- end
- end
- for i=nofsnippets,n+1,-1 do
- data[i] = nil
- end
- -- and this one because mp cannot handle snippets due to grouping issues
- if metapost.collapse then
- if #data > 1 then
- data = concat(data,"\n")
- else
- data = data[1]
- end
- end
- -- end of hacks
- end
-
+ local data = prepareddata(data,metapost.collapse)
local function process(d,i)
- -- d = string.gsub(d,"\r","")
if d then
if trace_graphics then
if i then
@@ -444,7 +485,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass,
end
end
starttiming(metapost.exectime)
- result = mpx:execute(d) -- some day we wil use a coroutine with textexts
+ result = mpx:execute(d)
stoptiming(metapost.exectime)
if trace_graphics and result then
local str = result.log or result.error
@@ -461,7 +502,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass,
end
end
if result.fig then
- converted = metapost.convert(result, trialrun, flusher, multipass, askedfig)
+ converted = metapost.convert(specification,result)
end
end
elseif i then
@@ -475,7 +516,6 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass,
if trace_tracingall then
mpx:execute("tracingall;")
end
- -- table.insert(data,2,"")
for i=1,#data do
process(data[i],i)
end
@@ -486,17 +526,25 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass,
process(data)
end
if trace_graphics then
- local banner = "\n% end graphic\n\n"
+ local banner = makeendbanner(specification)
tra.inp:write(banner)
tra.log:write(banner)
end
stoptiming(metapost)
+ metapost.popscriptrunner(mpx)
+ end
+ if mpxdone then
+ metapost.popformat()
end
return converted, result
end
-function metapost.convert()
- report_metapost('warning: no converter set')
+if not metapost.convert then
+
+ function metapost.convert()
+ report_metapost('warning: no converter set')
+ end
+
end
-- handy
@@ -564,7 +612,7 @@ end
-- goodie
-function metapost.quickanddirty(mpxformat,data,plugmode)
+function metapost.quickanddirty(mpxformat,data,incontext)
if not data then
mpxformat = "metafun"
data = mpxformat
@@ -584,7 +632,14 @@ function metapost.quickanddirty(mpxformat,data,plugmode)
end
}
local data = formatters["; beginfig(1) ;\n %s\n ; endfig ;"](data)
- metapost.process(mpxformat, { data }, false, flusher, false, false, "all", plugmode)
+ metapost.process {
+ mpx = mpxformat,
+ flusher = flusher,
+ askedfig = "all",
+ useplugins = incontext,
+ incontext = incontext,
+ data = { data },
+ }
if code then
return {
bbox = bbox or { 0, 0, 0, 0 },
@@ -619,7 +674,6 @@ do
local width = 0
local height = 0
local depth = 0
- local mpx = false
local flusher = {
startfigure = function(n,llx,lly,urx,ury)
@@ -637,13 +691,18 @@ do
end
}
- function metapost.simple(format,code) -- even less than metapost.quickcanddirty
- local mpx = metapost.format(format or "metafun","metafun")
+ function metapost.simple(format,code) -- even less than metapost.quickcanddirty
+ local mpx = metapost.pushformat { } -- takes defaults
-- metapost.setoutercolor(2)
- metapost.process(mpx,
- { "beginfig(1);", code, "endfig;" },
- false, flusher, false, false, 1, true -- last true is plugmode !
- )
+ metapost.process {
+ mpx = mpx,
+ flusher = flusher,
+ askedfig = 1,
+ useplugins = false,
+ incontext = false,
+ data = { "beginfig(1);", code, "endfig;" },
+ }
+ metapost.popformat()
if result then
local stream = concat(result," ")
result = nil -- cleanup
diff --git a/tex/context/base/mkiv/mtx-context-domotica.tex b/tex/context/base/mkiv/mtx-context-domotica.tex
index 83562ee30..5a162893b 100644
--- a/tex/context/base/mkiv/mtx-context-domotica.tex
+++ b/tex/context/base/mkiv/mtx-context-domotica.tex
@@ -29,7 +29,9 @@
%
% example: context --extra=domotica --openzwave ./config/fibaro/fgms.xml ./open-zwave-master/config/aeotec/zw100.xml
% example: context --extra=domotica --openzwave --pattern="./open-zwave-master/config/**.xml"
-% example: context --extra=domotica --hue hue-pragma-tasks.lua
+% example: context --extra=domotica --hue hue-pragma-tasks.lua
+% example: context --extra=domotica --hue pragma-youless-gas.lua --year=2018 --month=8
+% example: context --extra=domotica --hue pragma-youless-electricity.lua
%
% end help
@@ -161,8 +163,11 @@
\stopmode
+
\startmode[hue]
+ \usemodule[youless]
+
\starttext
\setupheadertexts
@@ -171,10 +176,22 @@
local arguments = document.arguments
local files = document.files
- local pattern = arguments.pattern
local filename = files[1]
-
- if filename then
+ local pattern = arguments.pattern
+ local year = arguments.year
+ local month = arguments.month
+
+ local action = (arguments.tasks and "task")
+ or (arguments.graphics and "graphics")
+ or (string.find(filename,"tasks") and "tasks")
+ or (string.find(filename,"electricity") and "graphics")
+ or (string.find(filename,"pulse") and "graphics")
+ or (string.find(filename,"gas") and "graphics")
+
+ if not filename or filename == "" then
+ logs.report("youless","provide filename")
+ context("no files given")
+ elseif action == "tasks" then
context.starttitle { title = "Hue: " .. file.nameonly(filename) }
filename = file.addsuffix(filename,"lua")
if lfs.isfile(filename) then
@@ -183,9 +200,11 @@
context("unknown file %a",filename)
end
context.stoptitle()
+ elseif action == "graphics" then
+ moduledata.youless.graphics { year = year, month = month, filename = filename }
else
- context("no files given")
- context.stoptitle()
+ logs.report("youless","provide --status or --graphics")
+ context("no action given")
end
\stopluacode
diff --git a/tex/context/base/mkiv/mtx-context-fonts.tex b/tex/context/base/mkiv/mtx-context-fonts.tex
new file mode 100644
index 000000000..f1f74c9e9
--- /dev/null
+++ b/tex/context/base/mkiv/mtx-context-fonts.tex
@@ -0,0 +1,98 @@
+%D \module
+%D [ file=mtx-context-fonts,
+%D version=2018.10.10,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Show Font Info,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% begin help
+%
+% usage: context --extra=fonts [options] name
+%
+% --topspace=dimension : distance above first line
+% --backspace=dimension : distance before left margin
+% --paperformat=spec : paper*print or paperxprint
+% --compact : small margins, 8pt font
+% --verycompact : small margins, 7pt font
+%
+% example: context --extra=fonts --name=dejavu-serif
+% end help
+
+\input mtx-context-common.tex
+
+\usemodule[fonts-charts]
+\usemodule[fonts-tables]
+
+\input mtx-context-common.tex
+
+\doifdocumentargument {compact} {
+ \setdocumentargument{topspace} {5mm}
+ \setdocumentargument{backspace}{5mm}
+ \setdocumentargument{bodyfont} {8pt}
+}
+
+\doifdocumentargument {verycompact} {
+ \setdocumentargument{topspace} {5mm}
+ \setdocumentargument{backspace}{5mm}
+ \setdocumentargument{bodyfont} {7pt}
+}
+
+\setupbodyfont
+ [dejavu,9pt,tt,\getdocumentargument{bodyfont}] % dejavu is more complete
+
+\setuplayout
+ [header=0cm,
+ footer=1.5cm,
+ topspace=\getdocumentargumentdefault{topspace}{1.5cm},
+ backspace=\getdocumentargumentdefault{backspace}{1.5cm},
+ width=middle,
+ height=middle]
+
+\setuppapersize
+ [\getdocumentargument{paperformat_paper}]
+ [\getdocumentargument{paperformat_print}]
+
+\starttexdefinition unexpanded showfontdetails [#1]
+ \starttitle[title=#1]
+ \startsubject[title=Properties]
+ \showfontproperties[#1]
+ \stopsubject
+ \startsubject[title=Parameters]
+ \showfontparameters[#1]
+ \stopsubject
+ \startsubject[title=Positionings]
+ \showfontpositionings[#1]
+ \stopsubject
+ \startsubject[title=Substitutions]
+ \showfontsubstitutions[#1]
+ \stopsubject
+ \startsubject[title=Unicodevariants]
+ \showfontunicodevariants[#1]
+ \stopsubject
+ \startsubject[title=Ligatures]
+ \showfontligatures[#1]
+ \stopsubject
+ \showfontchart[#1,page=yes]
+ \stoptitle
+\stoptexdefinition
+
+\starttext
+
+ \startluacode
+ local files = document.files
+ if #files > 0 then
+ for i=1,#files do
+ context.showfontdetails { name = files[i] .. "*default" }
+ end
+ else
+ context("No font name(s) given.")
+ end
+ \stopluacode
+
+\stoptext
diff --git a/tex/context/base/mkiv/mtx-context-listing.tex b/tex/context/base/mkiv/mtx-context-listing.tex
index f7c3d2868..1053e80b9 100644
--- a/tex/context/base/mkiv/mtx-context-listing.tex
+++ b/tex/context/base/mkiv/mtx-context-listing.tex
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D This is a \TEXEXEC\ features that has been moved to \MKIV.
+%D This is a \TEXEXEC\ feature that has been moved to \MKIV.
% begin help
%
@@ -44,7 +44,7 @@
}
\setupbodyfont
- [dejavu,11pt,tt,\getdocumentargument{bodyfont}] % dejavu is more complete
+ [dejavu,9pt,tt,\getdocumentargument{bodyfont}] % dejavu is more complete
\setuptyping
[lines=yes]
diff --git a/tex/context/base/mkiv/mtx-context-xml.tex b/tex/context/base/mkiv/mtx-context-xml.tex
index f8bfeef3a..875f02da6 100644
--- a/tex/context/base/mkiv/mtx-context-xml.tex
+++ b/tex/context/base/mkiv/mtx-context-xml.tex
@@ -76,6 +76,11 @@
if template then
moduledata.xml.analyzers.allsetups(files,type(template) == "string" and template or nil)
end
+ context.page()
+ for i=1,#files do
+ context.type(files[i])
+ context.par()
+ end
else
context("no action given")
end
diff --git a/tex/context/base/mkiv/mult-aux.mkiv b/tex/context/base/mkiv/mult-aux.mkiv
index a1aecc354..5e7de2270 100644
--- a/tex/context/base/mkiv/mult-aux.mkiv
+++ b/tex/context/base/mkiv/mult-aux.mkiv
@@ -180,6 +180,10 @@
\def\mult_check_for_assignment_indeed#1=#2#3\_end_
{\if#2@\assignmentfalse\else\assignmenttrue\fi}
+\def\mult_check_for_assignment_indeed_begin_#1=#2#3\_end_
+ {\if#2@}
+
+
\def\mult_check_for_assignment#1%
{\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=@@\_end_}
@@ -223,7 +227,8 @@
{\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing
\def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%
\def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
- \def#5##1##2{\ifx##1\relax\??empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ?
+ %\def#5##1##2{\ifx##1\relax\??empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ?
+ \def#5##1##2{\ifx##1\relax\??empty\else#4##1{##2}\fi}% is {} needed around ##1 ?
\def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}%
\def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack
\def#8##1{\begincsname#1#2:##1\endcsname}}
@@ -255,7 +260,8 @@
{\ifx#2\relax\let#2\empty\fi
\def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used?
\def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
- \def#5##1##2{\ifx##1\relax\else#4{##1}{##2}\fi}%
+ %\def#5##1##2{\ifx##1\relax\else#4{##1}{##2}\fi}%
+ \def#5##1##2{\ifx##1\relax\else#4##1{##2}\fi}%
\def#6{#1#2:}%
\def#7##1{#1##1:}%
\def#8{\ifx#2\empty\else\ifcsname#1#2:\s!parent\endcsname\else\expandafter\let\csname#1#2:\s!parent\endcsname#1\fi\fi}%
@@ -389,6 +395,43 @@
\the#7%
\let#4#9}}
+% \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%
+% \unexpanded\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child]
+% {\let#9#4%
+% \edef#4{##1}%
+% \ifthirdargument
+% \the#6% predefine
+% \edef#8{##2}%
+% \mult_check_for_parent{#1}{#3}#4#8%
+% \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
+% \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
+% \mult_interfaces_get_parameters{#1#4:}[##3]%
+% \else\ifsecondargument
+% \the#6% predefine
+% \ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##2}=@@\_end_
+% \edef#8{##2}%
+% \mult_check_for_parent{#1}{#3}#4#8%
+% \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}%
+% \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
+% \else
+% \let#8\empty
+% \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}%
+% \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
+% \mult_interfaces_get_parameters{#1#4:}[##2]%
+% \fi
+% \else
+% \the#6% predefine
+% \let#8\empty
+% \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}%
+% \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
+% \fi\fi
+% \the#7%
+% \let#4#9}}
+
\unexpanded\def\installdefinehandler#1#2#3%
{\normalexpanded
{\mult_interfaces_install_define_handler
@@ -466,7 +509,7 @@
\let#3#7%
\else\iffirstargument
% \mult_check_for_assignment{##1}%
- \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_
+ \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_
\ifassignment
% \setuplayout[key=value]
\let#7#3%
@@ -496,6 +539,54 @@
#2\zerocount % mode is always zero at the end
\the#9}}
+% \unexpanded\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9%
+% {\newtoks#5%
+% \newconstant#2%
+% \newtoks#8%
+% \newtoks#9%
+% \ifx#6\relax\let#6\empty\fi
+% \unexpanded\def#4[##1][##2]% maybe helper
+% {\ifsecondargument % no commalist here
+% % \setuplayout[whatever][key=value]
+% \let#7#3%
+% \let#6#3%
+% \edef#3{##1}%
+% #2\doingrootsetupnamed
+% \mult_interfaces_get_parameters{#1#3:}[##2]%
+% \the#5%
+% \ifx#3#6\the#8\fi % only switchsetups if previous == current
+% \let#3#7%
+% \else\iffirstargument
+% % \mult_check_for_assignment{##1}%
+% \ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##1}=@@\_end_
+% % \setuplayout[whatever]
+% \let#6#3% % previous becomes current
+% \edef#3{##1}% this will catch reset so one needs to test for it
+% #2\doingrootsetnamed
+% \the#5% % we can check for previous vs current
+% \the#8% switchsetups
+% \else
+% % \setuplayout[key=value]
+% \let#7#3%
+% \let#6#3%
+% \let#3\empty
+% #2\doingrootsetuproot
+% \mult_interfaces_get_parameters{#1:}[##1]%
+% \the#5%
+% \the#8% switchsetups
+% \let#3#7%
+% \fi
+% \else
+% % \setuplayout
+% \let#6#3% % previous becomes current
+% \let#3\empty % current becomes empty
+% #2\doingrootsetroot
+% \the#5%
+% \the#8% switchsetups
+% \fi\fi
+% #2\zerocount % mode is always zero at the end
+% \the#9}}
+
\unexpanded\def\installswitchsetuphandler#1#2%
{\normalexpanded
{\mult_interfaces_install_switch_setup_handler_a
@@ -966,176 +1057,176 @@
\def\s!double{double}
\def\s!triple{triple}
-\unexpanded\def\syst_helpers_double_empty#1#2#3%
- {\syst_helpers_argument_reset
- \doifelsenextoptional
- {\syst_helpers_double_empty_one_yes_mult#2#3}%
- {\syst_helpers_double_empty_one_nop_mult#1}}
-
-\def\syst_helpers_double_empty_one_yes_mult#1#2[#3]%
- {\firstargumenttrue
- \doifelsenextoptional
- {\secondargumenttrue#2[{#3}]}%
- {\syst_helpers_double_empty_two_nop_mult#1{#3}}}
-
-\def\syst_helpers_double_empty_one_nop_mult% #1%
- {\firstargumentfalse
- \secondargumentfalse
- }% #1}
-
-\def\syst_helpers_double_empty_two_nop_mult
- {\secondargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_double_empty_one_spaced_mult
- \else
- \expandafter\syst_helpers_double_empty_one_normal_mult
- \fi}
-
-\def\syst_helpers_double_empty_one_spaced_mult#1#2{#1[{#2}] }
-\def\syst_helpers_double_empty_one_normal_mult#1#2{#1[{#2}]}
-
-\unexpanded\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8%
- {\ifx#3\relax\let#3\empty\fi
- \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it
- \newtoks#4%
- \newtoks#7%
- \edef\m_mult_interface_setup{\csstring#2_}%
- \unexpanded\edef#2{\syst_helpers_double_empty
- \csname\m_mult_interface_setup\s!simple\endcsname
- \csname\m_mult_interface_setup\s!single\endcsname
- \csname\m_mult_interface_setup\s!double\endcsname}%
- \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!double\endcsname[##1][##2]%
- {\let#6#3%
- \def#8####1% we will have a simple one as well
- {\edef#3{####1}%
- \mult_interfaces_get_parameters{#1#3:}[##2]%
- \the#4}%
- \processcommalist[##1]#8%
- \let#3#6%
- \the#7}%
- \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!single\endcsname[##1]%
- {\let#6#3%
- \let#3\empty
- \mult_interfaces_get_parameters{#1:}[##1]%
- \the#4%
- \let#3#6%
- \the#7}%
- \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!simple\endcsname%
- {\let#6#3%
- \let#3\empty
- \the#4%
- \let#3#6%
- \the#7}}
-
-\unexpanded\def\installsetuphandler#1#2%
- {\normalexpanded
- {\mult_interfaces_install_setup_handler
- {\noexpand#1}% \??aa
- \expandafter\noexpand\csname setup#2\endcsname
- \expandafter\noexpand\csname current#2\endcsname
- \expandafter\noexpand\csname everysetup#2\endcsname
- \expandafter\noexpand\csname setupcurrent#2\endcsname
- \expandafter\noexpand\csname saved_setup_current#2\endcsname
- \expandafter\noexpand\csname everysetup#2root\endcsname
- \expandafter\noexpand\csname nested_setup_current#2\endcsname}}
-
-\unexpanded\def\syst_helpers_triple_empty#1#2#3#4%
- {\syst_helpers_argument_reset
- \doifelsenextoptional
- {\syst_helpers_triple_empty_one_yes_mult#2#3#4}%
- {\syst_helpers_triple_empty_one_nop_mult#1}}
-
-\def\syst_helpers_triple_empty_one_yes_mult#1#2#3[#4]%
- {\firstargumenttrue
- \doifelsenextoptional
- {\syst_helpers_triple_empty_two_yes_mult#2#3{#4}}%
- {\syst_helpers_triple_empty_two_nop_mult#1{#4}}}
-
-\def\syst_helpers_triple_empty_two_yes_mult#1#2#3[#4]%
- {\secondargumenttrue
- \doifelsenextoptional
- {\thirdargumenttrue#2[{#3}][{#4}]}%
- {\syst_helpers_triple_empty_three_nop_mult#1{#3}{#4}}}
-
-\def\syst_helpers_triple_empty_one_nop_mult % #1%
- {\firstargumentfalse
- \secondargumentfalse
- \thirdargumentfalse
- } % #1
-
-\def\syst_helpers_triple_empty_two_nop_mult
- {\secondargumentfalse
- \thirdargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_triple_empty_two_spaced_mult
- \else
- \expandafter\syst_helpers_triple_empty_two_normal_mult
- \fi}
-
-\def\syst_helpers_triple_empty_three_nop_mult
- {\thirdargumentfalse
- \if_next_blank_space_token
- \expandafter\syst_helpers_triple_empty_three_spaced_mult
- \else
- \expandafter\syst_helpers_triple_empty_three_normal_mult
- \fi}
-
-\def\syst_helpers_triple_empty_two_spaced_mult #1#2{#1[{#2}] }
-\def\syst_helpers_triple_empty_two_normal_mult #1#2{#1[{#2}]}
-\def\syst_helpers_triple_empty_three_spaced_mult#1#2#3{#1[{#2}][{#3}] }
-\def\syst_helpers_triple_empty_three_normal_mult#1#2#3{#1[{#2}][{#3}]}
-
-\unexpanded\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8%
- {\ifx#3\relax\let#3\empty\fi
- \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}%
- \newtoks#4%
- \edef\m_mult_interface_setup{\csstring#2_}%
- \unexpanded\edef#2{\syst_helpers_triple_empty
- \csname\m_mult_interface_setup\s!simple\endcsname
- \csname\m_mult_interface_setup\s!single\endcsname
- \csname\m_mult_interface_setup\s!double\endcsname
- \csname\m_mult_interface_setup\s!triple\endcsname}%
- \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!triple\endcsname[##1][##2][##3]%
- {\let#7#3%
- \def#8####1%
- {\edef#3{####1}%
- \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}%
- \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
- \the#4}%
- \processcommalist[##1]#8%
- \let#3#7}%
- \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!double\endcsname[##1][##2]%
- {\let#7#3%
- \def#8####1%
- {\edef#3{####1}%
- #6% checks parent and sets if needed
- \mult_interfaces_get_parameters{#1#3:}[##2]%
- \the#4}%
- \processcommalist[##1]#8%
- \let#3#7}%
- \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!single\endcsname[##1]%
- {\let#7#3%
- \let#3\empty
- \mult_interfaces_get_parameters{#1:}[##1]%
- \the#4%
- \let#3#7}%
- \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!simple\endcsname%
- {\let#7#3%
- \let#3\empty
- \the#4%
- \let#3#7}}
-
-\unexpanded\def\installautosetuphandler#1#2%
- {\normalexpanded
- {\mult_interfaces_install_auto_setup_handler
- {\noexpand#1}% \??aa
- \expandafter\noexpand\csname setup#2\endcsname
- \expandafter\noexpand\csname current#2\endcsname
- \expandafter\noexpand\csname everysetup#2\endcsname
- \expandafter\noexpand\csname setupcurrent#2\endcsname
- \expandafter\noexpand\csname check#2parent\endcsname
- \expandafter\noexpand\csname saved_setup_current#2\endcsname
- \expandafter\noexpand\csname nested_setup_current#2\endcsname}}
+% \unexpanded\def\syst_helpers_double_empty#1#2#3%
+% {\syst_helpers_argument_reset
+% \doifelsenextoptional
+% {\syst_helpers_double_empty_one_yes_mult#2#3}%
+% {\syst_helpers_double_empty_one_nop_mult#1}}
+%
+% \def\syst_helpers_double_empty_one_yes_mult#1#2[#3]%
+% {\firstargumenttrue
+% \doifelsenextoptional
+% {\secondargumenttrue#2[{#3}]}%
+% {\syst_helpers_double_empty_two_nop_mult#1{#3}}}
+%
+% \def\syst_helpers_double_empty_one_nop_mult% #1%
+% {\firstargumentfalse
+% \secondargumentfalse
+% }% #1}
+%
+% \def\syst_helpers_double_empty_two_nop_mult
+% {\secondargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_double_empty_one_spaced_mult
+% \else
+% \expandafter\syst_helpers_double_empty_one_normal_mult
+% \fi}
+%
+% \def\syst_helpers_double_empty_one_spaced_mult#1#2{#1[{#2}] }
+% \def\syst_helpers_double_empty_one_normal_mult#1#2{#1[{#2}]}
+%
+% \unexpanded\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8%
+% {\ifx#3\relax\let#3\empty\fi
+% \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it
+% \newtoks#4%
+% \newtoks#7%
+% \edef\m_mult_interface_setup{\csstring#2_}%
+% \unexpanded\edef#2{\syst_helpers_double_empty
+% \csname\m_mult_interface_setup\s!simple\endcsname
+% \csname\m_mult_interface_setup\s!single\endcsname
+% \csname\m_mult_interface_setup\s!double\endcsname}%
+% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!double\endcsname[##1][##2]%
+% {\let#6#3%
+% \def#8####1% we will have a simple one as well
+% {\edef#3{####1}%
+% \mult_interfaces_get_parameters{#1#3:}[##2]%
+% \the#4}%
+% \processcommalist[##1]#8%
+% \let#3#6%
+% \the#7}%
+% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!single\endcsname[##1]%
+% {\let#6#3%
+% \let#3\empty
+% \mult_interfaces_get_parameters{#1:}[##1]%
+% \the#4%
+% \let#3#6%
+% \the#7}%
+% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!simple\endcsname%
+% {\let#6#3%
+% \let#3\empty
+% \the#4%
+% \let#3#6%
+% \the#7}}
+
+% \unexpanded\def\installsetuphandler#1#2%
+% {\normalexpanded
+% {\mult_interfaces_install_setup_handler
+% {\noexpand#1}% \??aa
+% \expandafter\noexpand\csname setup#2\endcsname
+% \expandafter\noexpand\csname current#2\endcsname
+% \expandafter\noexpand\csname everysetup#2\endcsname
+% \expandafter\noexpand\csname setupcurrent#2\endcsname
+% \expandafter\noexpand\csname saved_setup_current#2\endcsname
+% \expandafter\noexpand\csname everysetup#2root\endcsname
+% \expandafter\noexpand\csname nested_setup_current#2\endcsname}}
+%
+% \unexpanded\def\syst_helpers_triple_empty#1#2#3#4%
+% {\syst_helpers_argument_reset
+% \doifelsenextoptional
+% {\syst_helpers_triple_empty_one_yes_mult#2#3#4}%
+% {\syst_helpers_triple_empty_one_nop_mult#1}}
+%
+% \def\syst_helpers_triple_empty_one_yes_mult#1#2#3[#4]%
+% {\firstargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_triple_empty_two_yes_mult#2#3{#4}}%
+% {\syst_helpers_triple_empty_two_nop_mult#1{#4}}}
+%
+% \def\syst_helpers_triple_empty_two_yes_mult#1#2#3[#4]%
+% {\secondargumenttrue
+% \doifelsenextoptional
+% {\thirdargumenttrue#2[{#3}][{#4}]}%
+% {\syst_helpers_triple_empty_three_nop_mult#1{#3}{#4}}}
+%
+% \def\syst_helpers_triple_empty_one_nop_mult % #1%
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% } % #1
+%
+% \def\syst_helpers_triple_empty_two_nop_mult
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_triple_empty_two_spaced_mult
+% \else
+% \expandafter\syst_helpers_triple_empty_two_normal_mult
+% \fi}
+%
+% \def\syst_helpers_triple_empty_three_nop_mult
+% {\thirdargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_triple_empty_three_spaced_mult
+% \else
+% \expandafter\syst_helpers_triple_empty_three_normal_mult
+% \fi}
+%
+% \def\syst_helpers_triple_empty_two_spaced_mult #1#2{#1[{#2}] }
+% \def\syst_helpers_triple_empty_two_normal_mult #1#2{#1[{#2}]}
+% \def\syst_helpers_triple_empty_three_spaced_mult#1#2#3{#1[{#2}][{#3}] }
+% \def\syst_helpers_triple_empty_three_normal_mult#1#2#3{#1[{#2}][{#3}]}
+%
+% \unexpanded\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8%
+% {\ifx#3\relax\let#3\empty\fi
+% \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}%
+% \newtoks#4%
+% \edef\m_mult_interface_setup{\csstring#2_}%
+% \unexpanded\edef#2{\syst_helpers_triple_empty
+% \csname\m_mult_interface_setup\s!simple\endcsname
+% \csname\m_mult_interface_setup\s!single\endcsname
+% \csname\m_mult_interface_setup\s!double\endcsname
+% \csname\m_mult_interface_setup\s!triple\endcsname}%
+% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!triple\endcsname[##1][##2][##3]%
+% {\let#7#3%
+% \def#8####1%
+% {\edef#3{####1}%
+% \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}%
+% \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
+% \the#4}%
+% \processcommalist[##1]#8%
+% \let#3#7}%
+% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!double\endcsname[##1][##2]%
+% {\let#7#3%
+% \def#8####1%
+% {\edef#3{####1}%
+% #6% checks parent and sets if needed
+% \mult_interfaces_get_parameters{#1#3:}[##2]%
+% \the#4}%
+% \processcommalist[##1]#8%
+% \let#3#7}%
+% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!single\endcsname[##1]%
+% {\let#7#3%
+% \let#3\empty
+% \mult_interfaces_get_parameters{#1:}[##1]%
+% \the#4%
+% \let#3#7}%
+% \unexpanded\expandafter\def\csname\m_mult_interface_setup\s!simple\endcsname%
+% {\let#7#3%
+% \let#3\empty
+% \the#4%
+% \let#3#7}}
+%
+% \unexpanded\def\installautosetuphandler#1#2%
+% {\normalexpanded
+% {\mult_interfaces_install_auto_setup_handler
+% {\noexpand#1}% \??aa
+% \expandafter\noexpand\csname setup#2\endcsname
+% \expandafter\noexpand\csname current#2\endcsname
+% \expandafter\noexpand\csname everysetup#2\endcsname
+% \expandafter\noexpand\csname setupcurrent#2\endcsname
+% \expandafter\noexpand\csname check#2parent\endcsname
+% \expandafter\noexpand\csname saved_setup_current#2\endcsname
+% \expandafter\noexpand\csname nested_setup_current#2\endcsname}}
% okay, we can also get rid of the #9, but this code looks pretty bad, while the previous is
% still okay given that we can also use #6 as setup (so in fact we can save some cs again and
@@ -1197,9 +1288,11 @@
{\dodoubleempty#7}%
\unexpanded\def#7[##1][##2]%
{\ifsecondargument
- #3\c_mult_set\expandafter{\the\c_mult_set#9[##1][##2]}%
+ %#3\c_mult_set\expandafter{\the\c_mult_set#9[##1][##2]}%
+ #3\toksapp\c_mult_set{#9[##1][##2]}%
\else\iffirstargument
- #3\c_mult_set\expandafter{\the\c_mult_set#8[##1]}%
+ %#3\c_mult_set\expandafter{\the\c_mult_set#8[##1]}%
+ #3\toksapp\c_mult_set{#8[##1]}%
\fi\fi}}
\unexpanded\def\installdefinitionsetmember#1#2#3#4%
@@ -1230,9 +1323,30 @@
\expandafter\noexpand\csname current#2parent\endcsname
\expandafter\noexpand\csname inject#2parent\endcsname}}
+% Faster but not used that much to make a dent in performance. But, because it's
+% cleaner anyway and also gives less tracing, we apply it a few times.
+
+\unexpanded\def\syst_helpers_install_macro_stack#1#2#3%
+ {\xdef\m_syst_helpers_push_macro{\csstring#1}%
+ \expandafter\newcount\csname#3\m_syst_helpers_push_macro\endcsname
+ \expandafter\edef\csname push_macro_\m_syst_helpers_push_macro\endcsname
+ {\noexpand\expandafter\glet
+ \noexpand\csname\m_syst_helpers_push_macro\noexpand\the\csname#3\m_syst_helpers_push_macro\endcsname\endcsname
+ \noexpand#1%
+ \global\advance\csname#3\m_syst_helpers_push_macro\endcsname\plusone}%
+ \expandafter\edef\csname pop_macro_\m_syst_helpers_push_macro\endcsname
+ {\global\advance\csname#3\m_syst_helpers_push_macro\endcsname\minusone
+ \noexpand\expandafter#2%
+ \noexpand\expandafter\noexpand#1%
+ \noexpand\csname\m_syst_helpers_push_macro\noexpand\the\csname#3\m_syst_helpers_push_macro\endcsname\endcsname}}
+
+\unexpanded\def\installmacrostack #1{\syst_helpers_install_macro_stack#1\let \??localpushedmacro }
+\unexpanded\def\installglobalmacrostack#1{\syst_helpers_install_macro_stack#1\glet\??globalpushedmacro}
+
\protect
-%\unprotect
+% \unprotect
+%
% \installcorenamespace {test} \installcommandhandler \??test {test} \??test
% \unexpanded\def\TestMeA[#1]%
% {\edef\currenttest{#1}
@@ -1247,12 +1361,92 @@
% \unexpanded\def\TestMeD[#1]%
% {\edef\currenttest{#1}
% \doubleexpandafter\ifx\testparameter\c!before\empty \relax \else \relax \fi}
-% \protect
%
-% \starttext
-% \definetest[foo] \definetest[bar][foo] \setuptest[bar][before=indeed]
-% \resettimer \dorecurse{100000}{\TestMeA[bar]} A:\elapsedtime \par % 0.502
-% \resettimer \dorecurse{100000}{\TestMeB[bar]} B:\elapsedtime \par % 0.530
-% \resettimer \dorecurse{100000}{\TestMeC[bar]} C:\elapsedtime \par % 0.487
-% \resettimer \dorecurse{100000}{\TestMeD[bar]} D:\elapsedtime \par % 0.493
-% \stoptext
+% \protect
+%
+% \starttext
+% \definetest[foo] \definetest[bar][foo] \setuptest[bar][before=indeed]
+% \resettimer \dorecurse{100000}{\TestMeA[bar]} A:\elapsedtime \par % 0.502
+% \resettimer \dorecurse{100000}{\TestMeB[bar]} B:\elapsedtime \par % 0.530
+% \resettimer \dorecurse{100000}{\TestMeC[bar]} C:\elapsedtime \par % 0.487
+% \resettimer \dorecurse{100000}{\TestMeD[bar]} D:\elapsedtime \par % 0.493
+% \stoptext
+
+% There is no real demand for this ... even if this is twice as fast we only gain
+% a few milliseconds:
+%
+% \unexpanded\def\foo#1{[foo:#1]}
+%
+% \installcommalistprocessor {foo} \foo
+% \installcommalistprocessorcommand \processfoolist {foo} \foo
+%
+% \commalistprocessor{foo}[a,b,c,d]
+% \processfoolist [a, b, c, d]
+%
+% \testfeatureonce{30000}{} \elapsedtime\par % 0.01 -> 0.00
+% \testfeatureonce{30000}{\processfoolist [fixed,middle]} \elapsedtime\par % 0.07 -> 0.06
+% \testfeatureonce{30000}{\commalistprocessor{foo}[fixed,middle]} \elapsedtime\par % 0.09 -> 0.08
+% \testfeatureonce{30000}{\processcommalist [fixed,middle]\foo} \elapsedtime\par % 0.13 -> 0.12
+%
+% For instance the luatex manual only has some 3000 calls. But I keep this around as one
+% never knows when we might need it.
+%
+% \installcorenamespace{commalistprocessor}
+% \installcorenamespace{commalistprocessorcheck}
+% \installcorenamespace{commalistprocessorwrap}
+% \installcorenamespace{commalistprocessorfirst}
+% \installcorenamespace{commalistprocessorcheckspace}
+% \installcorenamespace{commalistprocessorcheckfinish}
+% \installcorenamespace{commalistprocessoraction}
+% \installcorenamespace{commalistprocessorgobblespace}
+%
+% \unexpanded\def\installcommalistprocessor#1#2% 7 macro names overhead
+% {\let\nexttoken\relax
+% %
+% \unexpanded\expandafter\edef\csname\??commalistprocessor#1\endcsname[%
+% {\futurelet\nexttoken\csname\??commalistprocessorcheck#1\endcsname}%
+% %
+% \unexpanded\expandafter\edef\csname\??commalistprocessorcheck#1\endcsname
+% {\noexpand\ifx\nexttoken]%
+% \noexpand\expandafter\noexpand\gobblethreearguments
+% \noexpand\else
+% \noexpand\expandafter\csname\??commalistprocessorwrap#1\endcsname
+% \noexpand\fi
+% \relax}% this one preserved the next {}
+% %
+% \unexpanded\expandafter\edef\csname\??commalistprocessorwrap#1\endcsname##1]%
+% {\csname\??commalistprocessorfirst#1\endcsname##1,]\relax}%
+% %
+% \unexpanded\expandafter\edef\csname\??commalistprocessorfirst#1\endcsname##1% picks up \relax
+% {\csname\??commalistprocessorcheckspace#1\endcsname}%
+% %
+% \unexpanded\expandafter\edef\csname\??commalistprocessorcheckspace#1\endcsname
+% {\noexpand\ifx\nexttoken\noexpand\blankspace
+% \noexpand\expandafter\csname\??commalistprocessorgobblespace#1\endcsname
+% \noexpand\else
+% \noexpand\expandafter\csname\??commalistprocessorcheckfinish#1\endcsname
+% \noexpand\fi}%
+% %
+% \unexpanded\expandafter\edef\csname\??commalistprocessorcheckfinish#1\endcsname
+% {\noexpand\ifx\nexttoken]%
+% \noexpand\expandafter\noexpand\gobbleoneargument
+% \noexpand\else
+% \noexpand\expandafter\csname\??commalistprocessoraction#1\endcsname
+% \noexpand\fi}%
+% %
+% \unexpanded\expandafter\edef\csname\??commalistprocessoraction#1\endcsname##1,%
+% {\noexpand#2{##1}%
+% \futurelet\nexttoken\csname\??commalistprocessorcheckspace#1\endcsname}%
+% %
+% \let\next\:%
+% \unexpanded\edef \:{\csname\??commalistprocessorgobblespace#1\endcsname}%
+% \unexpanded\expandafter\edef\: {\futurelet\nexttoken\csname\??commalistprocessorcheckspace#1\endcsname}%
+% \let\:\next
+% %
+% }
+%
+% \unexpanded\def\installcommalistprocessorcommand#1#2#3%
+% {\installcommalistprocessor{#2}{#3}%
+% \expandafter\let\expandafter#1\csname\??commalistprocessor#2\endcsname}
+%
+% \unexpanded\def\commalistprocessor#1{\csname\??commalistprocessor#1\endcsname}
diff --git a/tex/context/base/mkiv/mult-def.lua b/tex/context/base/mkiv/mult-def.lua
index 925c22cd2..e03a82a76 100644
--- a/tex/context/base/mkiv/mult-def.lua
+++ b/tex/context/base/mkiv/mult-def.lua
@@ -7503,6 +7503,10 @@ return {
["pe"]="تاریخ",
["ro"]="data",
},
+ ["time"]={
+ ["en"]="time",
+ ["nl"]="tijd",
+ },
["deepnumbercommand"]={
["cs"]="deepnumbercommand",
["de"]="deepnumbercommand",
@@ -8278,7 +8282,7 @@ return {
["ro"]="inaltime",
},
["hfactor"]={
- ["cs"]="vfaktor",
+ ["cs"]="hfaktor",
["de"]="hfaktor",
["en"]="hfactor",
["fr"]="facteurhauteur",
@@ -8287,6 +8291,14 @@ return {
["pe"]="عامل‌ارتفاع",
["ro"]="hfactor",
},
+ ["vfactor"]={
+ ["cs"]="vfaktor",
+ ["de"]="vfaktor",
+ ["en"]="vfactor",
+ ["it"]="vfactor",
+ ["nl"]="vfactor",
+ ["ro"]="vfactor",
+ },
["hfil"]={
["cs"]="hfil",
["de"]="hfil",
@@ -11544,6 +11556,12 @@ return {
["pe"]="گام‌وای",
["ro"]="ystep",
},
+ ["ownerpassword"]={
+ ["en"]="ownerpassword",
+ },
+ ["userpassword"]={
+ ["en"]="userpassword",
+ },
},
["elements"]={
["answerlines"]={
@@ -13020,6 +13038,10 @@ return {
["cite"]={
["en"]="cite",
},
+ ["closed"]={
+ ["en"]="closed",
+ ["nl"]="gesloten",
+ },
["color"]={
["cs"]="barevne",
["de"]="farbe",
@@ -15538,7 +15560,7 @@ return {
["ro"]="postscript",
},
["precedingpage"]={
- ["en"]="followingpage",
+ ["en"]="precedingpage",
["nl"]="voorafgaandepagina",
},
["preference"]={
@@ -17053,6 +17075,9 @@ return {
["unframed"]={
["en"]="unframed",
},
+ ["unicode"]={
+ ["en"]="unicode",
+ },
["unit"]={
["cs"]="jednotka",
["de"]="einheit",
@@ -17815,8 +17840,8 @@ return {
["cd:brackets-l"] = { en = "[...,...]", lua = "{..., ...}" },
["cd:parenthesis-s"] = { en = "(...)" },
["cd:parenthesis-l"] = { en = "(...,...)" },
- ["cd:index-s"] = { en = "[...]" },
- ["cd:index-l"] = { en = "[..+...+..]" },
+ ["cd:index-s"] = { en = "{...}" },
+ ["cd:index-l"] = { en = "{..+...+..}" },
["cd:math-s"] = { en = "$...$" },
["cd:math-l"] = { en = "$...$" },
["cd:inlinemath-s"] = { en = "$...$" },
diff --git a/tex/context/base/mkiv/mult-fun.lua b/tex/context/base/mkiv/mult-fun.lua
index 9b7062605..0776f36b4 100644
--- a/tex/context/base/mkiv/mult-fun.lua
+++ b/tex/context/base/mkiv/mult-fun.lua
@@ -3,7 +3,7 @@ return {
--
"nocolormodel", "greycolormodel", "graycolormodel", "rgbcolormodel", "cmykcolormodel",
"shadefactor",
- "textextoffset",
+ "textextoffset", "textextanchor",
"normaltransparent", "multiplytransparent", "screentransparent", "overlaytransparent",
"softlighttransparent", "hardlighttransparent", "colordodgetransparent", "colorburntransparent",
"darkentransparent", "lightentransparent", "differencetransparent", "exclusiontransparent",
@@ -53,17 +53,19 @@ return {
"shadedinto", "withshadecolors",
"withshadedomain", "withshademethod", "withshadefactor", "withshadevector",
"withshadecenter", "withshadedirection", "withshaderadius", "withshadetransform",
- "withshadestep", "withshadefraction",
+ "withshadestep", "withshadefraction", "withshadeorigin", "shownshadevector", "shownshadeorigin",
"cmyk", "spotcolor", "multitonecolor", "namedcolor",
"drawfill", "undrawfill",
"inverted", "uncolored", "softened", "grayed", "greyed",
"onlayer",
"along",
- "graphictext", "loadfigure", "externalfigure", "figure", "register", "outlinetext", -- "lua",
+ "graphictext", "loadfigure", "externalfigure", "figure", "register",
+ "outlinetext", "filloutlinetext", "drawoutlinetext", "outlinetexttopath",
"checkedbounds", "checkbounds", "strut", "rule",
"withmask", "bitmapimage",
"colordecimals", "ddecimal", "dddecimal", "ddddecimal", "colordecimalslist",
"textext", "thetextext", "rawtextext", "textextoffset", "texbox", "thetexbox", "rawtexbox", "istextext",
+ "notcached",
"verbatim",
"thelabel", "label",
"autoalign",
@@ -144,5 +146,31 @@ return {
"sortlist", "copylist", "shapedlist", "listtocurves", "listtolines", "listsize", "listlast", "uniquelist",
--
"circularpath", "squarepath", "linearpath",
+ --
+ "theoffset",
+ --
+ "texmode", "systemmode",
+ "texvar", "texstr",
+ "isarray", "prefix", "dimension",
+ "getmacro", "getdimen", "getcount", "gettoks",
+ "setmacro", "setdimen", "setcount", "settoks",
+ --
+ "positionpath", "positioncurve", "positionxy", "positionpxy",
+ "positionwhd", "positionpage", "positionregion", "positionbox",
+ "positionanchor", "positioninregion", "positionatanchor",
+ --
+ "wdpart", "htpart", "dppart",
+ --
+ "texvar", "texstr",
+ --
+ "inpath", "pointof", "leftof", "rightof",
+ --
+ "newhash", "disposehash", "inhash", "tohash",
+ --
+ "isarray", "prefix", "isobject",
+ --
+ "comment", "report", "lua", "mp", "MP", "luacall",
+ --
+ "mirrored", "mirroredabout",
},
}
diff --git a/tex/context/base/mkiv/mult-ini.lua b/tex/context/base/mkiv/mult-ini.lua
index 3f320bf7f..0c8581281 100644
--- a/tex/context/base/mkiv/mult-ini.lua
+++ b/tex/context/base/mkiv/mult-ini.lua
@@ -105,6 +105,22 @@ function interfaces.getnamespace(n)
return usednamespaces[n] .. ">"
end
+if documentdata then
+
+ local prefix, getmacro
+
+ function documentdata.variable(name)
+ if not prefix then
+ prefix = usednamespaces.variables .. ">document:"
+ end
+ if not getmacro then
+ getmacro = tokens.getters.macro
+ end
+ return getmacro(prefix..name)
+ end
+
+end
+
local function resolve(t,k)
local v = logs.reporter(k)
t[k] = v
diff --git a/tex/context/base/mkiv/mult-ini.mkiv b/tex/context/base/mkiv/mult-ini.mkiv
index d66749d14..634e2c1d8 100644
--- a/tex/context/base/mkiv/mult-ini.mkiv
+++ b/tex/context/base/mkiv/mult-ini.mkiv
@@ -111,6 +111,8 @@
\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!left {left}
+\def\s!right {right}
\def\s!fil {fil}
\def\s!fill {fill} \let\!!fill \s!fill % obsolete
\def\s!filll {filll}
@@ -122,11 +124,6 @@
\def\s!top {top}
\def\s!both {both}
-%D Kind of special:
-
-\edef\!!TLT{\detokenize{TLT}}
-\edef\!!TRT{\detokenize{TRT}}
-
%D \macros
%D {defineinterfaceconstant,
%D defineinterfacevariable,
@@ -341,17 +338,17 @@
%D These will become obsolete:
\unexpanded\def\startmessages #1 library: #2 %
- {\bgroup
+ {\begingroup
\ifcsname\m!prefix!#2\endcsname\else\setgvalue{\m!prefix!#2}{#2}\fi
- \catcode\endoflineasciicode\activecatcode
+ \catcode\endoflineasciicode\othercatcode
\doifelseinset{#1}{\currentresponses,all}\mult_messages_start_yes\mult_messages_start_nop{#2}}
\def\mult_messages_start_yes#1#2\stopmessages
{\clf_setinterfacemessages{#1}{#2}%
- \egroup}
+ \endgroup}
\def\mult_messages_start_nop#1#2\stopmessages
- {\egroup}
+ {\endgroup}
\let\stopmessages\relax
diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua
index 0acba3b87..75c048c92 100644
--- a/tex/context/base/mkiv/mult-low.lua
+++ b/tex/context/base/mkiv/mult-low.lua
@@ -12,7 +12,8 @@ return {
["constants"] = {
--
"zerocount", "minusone", "minustwo", "plusone", "plustwo", "plusthree", "plusfour", "plusfive",
- "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen", "plushundred", "plustwohundred",
+ "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen",
+ "plusfifty", "plushundred", "plusonehundred", "plustwohundred", "plusfivehundred",
"plusthousand", "plustenthousand", "plustwentythousand", "medcard", "maxcard", "maxcardminusone",
"zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxcount", "maxdimen", "scaledpoint", "thousandpoint",
"points", "halfpoint",
@@ -20,7 +21,9 @@ return {
"zeromuskip", "onemuskip",
"pluscxxvii", "pluscxxviii", "pluscclv", "pluscclvi",
"normalpagebox",
- -- --
+ --
+ "directionlefttoright", "directionrighttoleft",
+ --
"endoflinetoken", "outputnewlinechar",
--
"emptytoks", "empty", "undefined",
@@ -31,9 +34,7 @@ return {
--
"fmtname", "fmtversion", "texengine", "texenginename", "texengineversion", "texenginefunctionality",
"luatexengine", "pdftexengine", "xetexengine", "unknownengine",
- -- "etexversion",
- -- "pdftexversion", "pdftexrevision",
- -- "xetexversion", "xetexrevision",
+ "contextformat", "contextversion", "contextkind", "contextlmtxmode", "contextmark", "mksuffix",
--
"activecatcode",
--
@@ -59,6 +60,7 @@ return {
"spaceasciicode", "hashasciicode", "dollarasciicode", "commentasciicode", "ampersandasciicode",
"colonasciicode", "backslashasciicode", "circumflexasciicode", "underscoreasciicode",
"leftbraceasciicode", "barasciicode", "rightbraceasciicode", "tildeasciicode", "delasciicode",
+ "leftparentasciicode", "rightparentasciicode",
"lessthanasciicode", "morethanasciicode", "doublecommentsignal",
"atsignasciicode", "exclamationmarkasciicode", "questionmarkasciicode",
"doublequoteasciicode", "singlequoteasciicode", "forwardslashasciicode",
@@ -101,7 +103,9 @@ return {
"startcomponent", "stopcomponent", "component",
"startproduct", "stopproduct", "product",
"startproject", "stopproject", "project",
- "starttext", "stoptext", "startnotext", "stopnotext","startdocument", "stopdocument", "documentvariable", "unexpandeddocumentvariable", "setupdocument", "presetdocument",
+ "starttext", "stoptext", "startnotext", "stopnotext",
+ "startdocument", "stopdocument", "documentvariable", "unexpandeddocumentvariable", "setupdocument", "presetdocument",
+ "doifelsedocumentvariable", "doifdocumentvariableelse", "doifdocumentvariable", "doifnotdocumentvariable",
"startmodule", "stopmodule", "usemodule", "usetexmodule", "useluamodule","setupmodule","currentmoduleparameter","moduleparameter",
"everystarttext", "everystoptext",
--
@@ -153,10 +157,12 @@ return {
"texdefinition",
--
"doifelsesetups", "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup", "fastsetup",
+ "copysetups", "resetsetups",
"doifelsecommandhandler", "doifcommandhandlerelse", "doifnotcommandhandler", "doifcommandhandler",
--
"newmode", "setmode", "resetmode",
"newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode",
+ "globalsetmode", "globalresetmode", "globalsetsystemmode", "globalresetsystemmode",
"booleanmodevalue",
--
"newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newread", "newwrite", "newmarks", "newinsert", "newattribute", "newif",
@@ -165,14 +171,19 @@ return {
"then",
"begcsname",
--
+ "autorule",
+ --
"strippedcsname","checkedstrippedcsname",
--
"firstargumentfalse", "firstargumenttrue",
"secondargumentfalse", "secondargumenttrue",
"thirdargumentfalse", "thirdargumenttrue",
"fourthargumentfalse", "fourthargumenttrue",
- "fifthargumentfalse", "fifthsargumenttrue",
- "sixthargumentfalse", "sixtsargumenttrue",
+ "fifthargumentfalse", "fifthargumenttrue",
+ "sixthargumentfalse", "sixthargumenttrue",
+ "seventhargumentfalse", "seventhargumenttrue",
+ --
+ "vkern", "hkern",
--
"doglobal", "dodoglobal", "redoglobal", "resetglobal",
--
@@ -197,8 +208,8 @@ return {
--
"hglue", "vglue", "hfillneg", "vfillneg", "hfilllneg", "vfilllneg",
--
- "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg",
- "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg",
+ "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilll", "ruledhfilneg", "ruledhfillneg", "normalhfillneg", "normalhfilllneg",
+ "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilll", "ruledvfilneg", "ruledvfillneg", "normalvfillneg", "normalvfilllneg",
"ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter", "ruledmbox",
"ruledhpack", "ruledvpack", "ruledtpack",
"ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern",
@@ -214,11 +225,20 @@ return {
"scratchtoks", "globalscratchtoks", "privatescratchtoks",
"scratchbox", "globalscratchbox", "privatescratchbox",
--
+ "globalscratchcounterone", "globalscratchcountertwo", "globalscratchcounterthree",
+ --
+ "groupedcommand", "groupedcommandcs",
+ "triggergroupedcommand", "triggergroupedcommandcs",
+ "simplegroupedcommand", "pickupgroupedcommand",
+ --
"normalbaselineskip", "normallineskip", "normallineskiplimit",
--
"availablehsize", "localhsize", "setlocalhsize", "distributedhsize", "hsizefraction",
--
+ "next", "nexttoken",
+ --
"nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs", "flushnextbox",
+ "boxisempty",
--
"scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance",
"scratchhsize", "scratchvsize",
@@ -239,6 +259,7 @@ return {
"scratchleftskip", "scratchrightskip", "scratchtopskip", "scratchbottomskip",
--
"doif", "doifnot", "doifelse",
+ "firstinset",
"doifinset", "doifnotinset",
"doifelseinset", "doifinsetelse",
"doifelsenextchar", "doifnextcharelse",
@@ -262,7 +283,7 @@ return {
"doifelsenumber", "doifnumberelse", "doifnumber", "doifnotnumber",
"doifelsecommon", "doifcommonelse", "doifcommon", "doifnotcommon",
"doifinstring", "doifnotinstring", "doifelseinstring", "doifinstringelse",
- "doifelseassignment", "doifassignmentelse", "docheckassignment",
+ "doifelseassignment", "doifassignmentelse", "docheckassignment", "doifelseassignmentcs", "doifassignmentelsecs",
"doiftext", "doifelsetext", "doiftextelse", "doifnottext",
--
"tracingall", "tracingnone", "loggingall",
@@ -278,7 +299,7 @@ return {
"singleexpandafter", "doubleexpandafter", "tripleexpandafter",
--
"dontleavehmode", "removelastspace", "removeunwantedspaces", "keepunwantedspaces",
- "removepunctuation", "ignoreparskip", "forcestrutdepth",
+ "removepunctuation", "ignoreparskip", "forcestrutdepth", "onlynonbreakablespace",
--
"wait", "writestatus", "define", "defineexpandable", "redefine",
--
@@ -329,7 +350,7 @@ return {
"dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty",
"permitspacesbetweengroups", "dontpermitspacesbetweengroups",
--
- "nopdfcompression", "maximumpdfcompression", "normalpdfcompression",
+ "nopdfcompression", "maximumpdfcompression", "normalpdfcompression", "onlypdfobjectcompression", "nopdfobjectcompression",
--
"modulonumber", "dividenumber",
--
@@ -403,12 +424,8 @@ return {
"startluacode", "stopluacode", "startlua", "stoplua",
"startctxfunction","stopctxfunction","ctxfunction",
"startctxfunctiondefinition","stopctxfunctiondefinition",
- "installctxfunction", "installctxfunctioncall",
- "installprotectedctxfunction", "installprotectedctxfunctioncall",
- "installctxscanner", "installctxscannercall",
- "resetctxscanner",
- "installprotectedctxscanner", "installprotectedctxscannercall",
- "cldprocessfile", "cldloadfile", "cldcontext", "cldcommand",
+ "installctxfunction", "installprotectedctxfunction", "installprotectedctxscanner", "installctxscanner", "resetctxscanner",
+ "cldprocessfile", "cldloadfile", "cldloadviafile", "cldcontext", "cldcommand",
--
"carryoverpar",
"lastlinewidth",
@@ -433,7 +450,8 @@ return {
--
"nospace", "nospacing", "dospacing",
--
- "naturalhbox", "naturalvbox", "naturalvtop", "naturalhpack", "naturalvpack",
+ "naturalhbox", "naturalvbox", "naturalvtop", "naturalhpack", "naturalvpack", "naturaltpack",
+ "reversehbox", "reversevbox", "reversevtop", "reversehpack", "reversevpack", "reversetpack",
--
"frule",
--
diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua
index 1cd5f5810..579750bc9 100644
--- a/tex/context/base/mkiv/mult-prm.lua
+++ b/tex/context/base/mkiv/mult-prm.lua
@@ -231,35 +231,44 @@ return {
"breakafterdirmode",
"catcodetable",
"clearmarks",
- "copyfont",
"compoundhyphenmode",
+ "copyfont",
"crampeddisplaystyle",
"crampedscriptscriptstyle",
"crampedscriptstyle",
"crampedtextstyle",
+ "csstring",
"draftmode",
"dviextension",
"dvifeedback",
"dvivariable",
"efcode",
+ "endlocalcontrol",
"etoksapp",
"etokspre",
+ "exceptionpenalty",
"expanded",
"expandglyphsinfont",
"explicitdiscretionary",
"explicithyphenpenalty",
+ "fixupboxesmode",
"fontid",
"formatname",
"gleaders",
+ "gtoksapp",
+ "gtokspre",
"hjcode",
"hyphenationbounds",
"hyphenationmin",
"hyphenpenaltymode",
"ifabsdim",
"ifabsnum",
+ "ifcondition",
"ifincsname",
"ifprimitive",
"ignoreligaturesinfont",
+ "immediateassigned",
+ "immediateassignment",
"initcatcodetable",
"insertht",
"lastnamedcs",
@@ -269,6 +278,7 @@ return {
"lastxpos",
"lastypos",
"latelua",
+ "lateluafunction",
"leftghost",
"leftmarginkern",
"letcharcode",
@@ -280,6 +290,10 @@ return {
"localleftbox",
"localrightbox",
"lpcode",
+ "luabytecode",
+ "luabytecodecall",
+ "luacopyinputnodes",
+ "luadef",
"luaescapestring",
"luafunction",
"luafunctioncall",
@@ -291,14 +305,17 @@ return {
"mathdirection",
"mathdisplayskipmode",
"matheqnogapstep",
+ "mathflattenmode",
"mathitalicsmode",
"mathnolimitsmode",
"mathoption",
"mathpenaltiesmode",
"mathrulesfam",
"mathrulesmode",
- "mathscriptsmode",
+ "mathrulethicknessmode",
"mathscriptboxmode",
+ "mathscriptcharmode",
+ "mathscriptsmode",
"mathstyle",
"mathsurroundmode",
"mathsurroundskip",
@@ -362,6 +379,8 @@ return {
"uniformdeviate",
"useboxresource",
"useimageresource",
+ "xtoksapp",
+ "xtokspre",
},
["omega"]={
"Omegaminorversion",
@@ -422,15 +441,17 @@ return {
"pdflastypos",
"pdflinkmargin",
"pdfliteral",
+ "pdfmajorversion",
"pdfmapfile",
"pdfmapline",
- "pdfmajorversion",
"pdfminorversion",
"pdfnames",
"pdfnoligatures",
"pdfnormaldeviate",
"pdfobj",
"pdfobjcompresslevel",
+ "pdfomitcharset",
+ "pdfomitcidset",
"pdfoutline",
"pdfoutput",
"pdfpageattr",
@@ -447,6 +468,7 @@ return {
"pdfprotrudechars",
"pdfpxdimen",
"pdfrandomseed",
+ "pdfrecompress",
"pdfrefobj",
"pdfrefxform",
"pdfrefximage",
@@ -522,7 +544,6 @@ return {
"cr",
"crcr",
"csname",
- "csstring",
"day",
"deadcycles",
"def",
@@ -580,6 +601,7 @@ return {
"fontname",
"futurelet",
"gdef",
+ "glet",
"global",
"globaldefs",
"halign",
@@ -823,4 +845,4 @@ return {
["xetex"]={
"XeTeXversion",
},
-}
+} \ No newline at end of file
diff --git a/tex/context/base/mkiv/mult-prm.mkiv b/tex/context/base/mkiv/mult-prm.mkiv
index 1b9195f41..5ffb84d38 100644
--- a/tex/context/base/mkiv/mult-prm.mkiv
+++ b/tex/context/base/mkiv/mult-prm.mkiv
@@ -55,7 +55,7 @@
"pdflastobj", "pdflastxform", "pdflastximage", "pdflastximagepages",
"pdflastxpos", "pdflastypos", "pdflinkmargin", "pdfliteral",
"pdfmapfile", "pdfmapline", "pdfmajorversion", "pdfminorversion", "pdfnames",
- "pdfnoligatures", "pdfnormaldeviate", "pdfobj",
+ "pdfnoligatures", "pdfnormaldeviate", "pdfobj", "pdfrecompress",
"pdfobjcompresslevel", "pdfoutline", "pdfoutput", "pdfpageattr",
"pdfpagebox", "pdfpageheight", "pdfpageref", "pdfpageresources",
"pdfpagesattr", "pdfpagewidth", "pdfpkfixeddpi", "pdfpkmode",
@@ -68,6 +68,7 @@
"pdftracingfonts", "pdftrailer", "pdftrailerid", "pdfuniformdeviate",
"pdfuniqueresname", "pdfvorigin", "pdfxform", "pdfxformattr",
"pdfxformmargin", "pdfxformname", "pdfxformresources", "pdfximage",
+ "pdfomitcidset", "pdfomitcharset",
},
aleph = { -- we don't bother
"Alephminorversion", "Alephrevision", "Alephversion",
diff --git a/tex/context/base/mkiv/mult-sys.mkiv b/tex/context/base/mkiv/mult-sys.mkiv
index 7000eed7b..fdb2ea732 100644
--- a/tex/context/base/mkiv/mult-sys.mkiv
+++ b/tex/context/base/mkiv/mult-sys.mkiv
@@ -55,6 +55,7 @@
\definesystemconstant {danish} \definesystemconstant {da}
\definesystemconstant {dutch} \definesystemconstant {nl}
\definesystemconstant {english} \definesystemconstant {en}
+\definesystemconstant {estonian} \definesystemconstant {et}
\definesystemconstant {farsi} \definesystemconstant {fa} % just persian
\definesystemconstant {finnish} \definesystemconstant {fi}
\definesystemconstant {french} \definesystemconstant {fr}
@@ -240,6 +241,7 @@
\definesystemconstant {next}
\definesystemconstant {pickup}
+\definesystemconstant {forget}
\definesystemconstant {ascii}
\definesystemconstant {default}
\definesystemconstant {unknown}
diff --git a/tex/context/base/mkiv/node-acc.lua b/tex/context/base/mkiv/node-acc.lua
index 03f6d7476..e6c617602 100644
--- a/tex/context/base/mkiv/node-acc.lua
+++ b/tex/context/base/mkiv/node-acc.lua
@@ -8,7 +8,6 @@ if not modules then modules = { } end modules ['node-acc'] = {
local nodes, node = nodes, node
-local nodecodes = nodes.nodecodes
local tasks = nodes.tasks
local nuts = nodes.nuts
@@ -16,6 +15,7 @@ local tonut = nodes.tonut
local tonode = nodes.tonode
local getid = nuts.getid
+local getsubtype = nuts.getsubtype
local getattr = nuts.getattr
local getlist = nuts.getlist
local getchar = nuts.getchar
@@ -28,21 +28,28 @@ local setsubtype = nuts.setsubtype
local getwidth = nuts.getwidth
local setwidth = nuts.setwidth
------ traverse_nodes = nuts.traverse
-local traverse_id = nuts.traverse_id
+local nextglyph = nuts.traversers.glyph
+local nextnode = nuts.traversers.node
+
----- copy_node = nuts.copy
local insert_after = nuts.insert_after
local copy_no_components = nuts.copy_no_components
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+
local glue_code = nodecodes.glue
----- kern_code = nodecodes.kern
local glyph_code = nodecodes.glyph
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
+local userskip_code = gluecodes.user
+local spaceskip_code = gluecodes.spaceskip
+local xspaceskip_code = gluecodes.xspaceskip
+
local a_characters = attributes.private("characters")
-local threshold = 65536 -- not used
local nofreplaced = 0
-- todo: nbsp etc
@@ -50,6 +57,9 @@ local nofreplaced = 0
-- todo: maybe cache as we now create many nodes
-- todo: check for subtype related to spacing (13/14 but most seems to be user anyway)
+local trace = false trackers.register("backend.spaces", function(v) trace = v end)
+local slot = nil
+
local function injectspaces(head)
local p, p_id
local n = head
@@ -57,32 +67,42 @@ local function injectspaces(head)
local id = getid(n)
if id == glue_code then
if p and getid(p) == glyph_code then
- -- unless we don't care about the little bit of overhead
- -- we can just: local g = copy_node(g)
- local g = copy_no_components(p)
- local a = getattr(n,a_characters)
- setchar(g,32)
- setlink(p,g,n)
- setwidth(n,getwidth(n) - getwidth(g))
- if a then
- setattr(g,a_characters,a)
+ local s = getsubtype(n)
+ if s == spaceskip_code or s == xspaceskip_code then
+ -- unless we don't care about the little bit of overhead
+ -- we can just: local g = copy_node(g)
+ local g = copy_no_components(p)
+ local a = getattr(n,a_characters)
+ setchar(g,slot)
+ setlink(p,g,n)
+ setwidth(n,getwidth(n) - getwidth(g))
+ -- setsubtype(n,userskip_code)
+ if a then
+ setattr(g,a_characters,a)
+ end
+ setattr(n,a_characters,0)
+ nofreplaced = nofreplaced + 1
end
- setattr(n,a_characters,0)
- nofreplaced = nofreplaced + 1
end
elseif id == hlist_code or id == vlist_code then
- injectspaces(getlist(n),attribute)
+ injectspaces(getlist(n),slot)
end
p_id = id
p = n
n = getnext(n)
end
- return head, true -- always done anyway
+ return head
end
nodes.handlers.accessibility = function(head)
- local head, done = injectspaces(tonut(head))
- return tonode(head), done
+ if trace then
+ if not slot then
+ slot = fonts.helpers.privateslot("visualspace")
+ end
+ else
+ slot = 32
+ end
+ return injectspaces(head,slot)
end
statistics.register("inserted spaces in output",function()
@@ -99,7 +119,7 @@ end)
--
-- local function compact(n)
-- local t = { }
--- for n in traverse_id(glyph_code,n) do
+-- for n in nextglyph, n do
-- t[#t+1] = utfchar(getchar(n)) -- check for unicode
-- end
-- return concat(t,"")
@@ -107,8 +127,7 @@ end)
--
-- local function injectspans(head)
-- local done = false
--- for n in traverse_nodes(tonuts(head)) do
--- local id = getid(n)
+-- for n, id in nextnode, tonuts(head) do
-- if id == disc then
-- local r = getfield(n,"replace")
-- local p = getfield(n,"pre")
@@ -134,18 +153,17 @@ end)
--
-- tasks.appendaction("processors", "words", "nodes.injectspans")
--
--- local pdfpageliteral = nuts.pool.pdfpageliteral
+-- local pageliteral = nuts.pool.pageliteral
--
-- local function injectspans(head)
-- local done = false
--- for n in traverse_nodes(tonut(head)) do
--- local id = getid(n)
+-- for n, id in nextnode, tonut(head) do
-- if id == disc then
-- local a = getattr(n,a_hyphenated)
-- if a then
-- local str = codes[a]
--- local b = pdfpageliteral(format("/Span << /ActualText %s >> BDC", lpdf.tosixteen(str)))
--- local e = pdfpageliteral("EMC")
+-- local b = pageliteral(format("/Span << /ActualText %s >> BDC", lpdf.tosixteen(str)))
+-- local e = pageliteral("EMC")
-- insert_before(head,n,b)
-- insert_after(head,n,e)
-- done = true
diff --git a/tex/context/base/mkiv/node-aux.lua b/tex/context/base/mkiv/node-aux.lua
index 84567068b..d6a9950fe 100644
--- a/tex/context/base/mkiv/node-aux.lua
+++ b/tex/context/base/mkiv/node-aux.lua
@@ -32,8 +32,6 @@ local getnext = nuts.getnext
local getid = nuts.getid
local getsubtype = nuts.getsubtype
local getlist = nuts.getlist
-local getfont = nuts.getfont
-local getchar = nuts.getchar
local getattr = nuts.getattr
local getboth = nuts.getboth
local getcomponents = nuts.getcomponents
@@ -51,8 +49,10 @@ local setprev = nuts.setprev
local setcomponents = nuts.setcomponents
local setattrlist = nuts.setattrlist
-local traverse_nodes = nuts.traverse
-local traverse_id = nuts.traverse_id
+----- traverse_nodes = nuts.traverse
+----- traverse_id = nuts.traverse_id
+local nextnode = nuts.traversers.node
+local nextglyph = nuts.traversers.glyph
local flush_node = nuts.flush
local flush_list = nuts.flush_list
local hpack_nodes = nuts.hpack
@@ -154,9 +154,8 @@ function nodes.repackhlist(list,...)
end
local function set_attributes(head,attr,value)
- for n in traverse_nodes(head) do
+ for n, id in nextnode, head do
setattr(n,attr,value)
- local id = getid(n)
if id == hlist_node or id == vlist_node then
set_attributes(getlist(n),attr,value)
end
@@ -164,11 +163,10 @@ local function set_attributes(head,attr,value)
end
local function set_unset_attributes(head,attr,value)
- for n in traverse_nodes(head) do
+ for n, id in nextnode, head do
if not getattr(n,attr) then
setattr(n,attr,value)
end
- local id = getid(n)
if id == hlist_code or id == vlist_code then
set_unset_attributes(getlist(n),attr,value)
end
@@ -176,9 +174,8 @@ local function set_unset_attributes(head,attr,value)
end
local function unset_attributes(head,attr)
- for n in traverse_nodes(head) do
+ for n, id in nextnode, head do
setattr(n,attr,unsetvalue)
- local id = getid(n)
if id == hlist_code or id == vlist_code then
unset_attributes(getlist(n),attr)
end
@@ -197,98 +194,11 @@ nuts.setattributes = set_attributes nodes.setattributes
nuts.setunsetattributes = set_unset_attributes nodes.setunsetattributes = vianuts(set_unset_attributes)
nuts.unsetattributes = unset_attributes nodes.unsetattributes = vianuts(unset_attributes)
--- history:
---
--- local function glyph_width(a)
--- local ch = chardata[getfont(a)][getchar(a)]
--- return (ch and ch.width) or 0
--- end
---
--- local function glyph_total(a)
--- local ch = chardata[getfont(a)][getchar(a)]
--- return (ch and (ch.height+ch.depth)) or 0
--- end
---
--- local function non_discardable(a) -- inline
--- return getid(id) < math_node -- brrrr
--- end
---
--- local function calculate_badness(t,s)
--- if t == 0 then
--- return 0
--- elseif s <= 0 then
--- return INF_BAD
--- else
--- local r
--- if t <= 7230584 then
--- r = t * 297 / s
--- elseif s >= 1663497 then
--- r = t / floor(s / 297)
--- else
--- r = t
--- end
--- r = floor(r)
--- if r > 1290 then
--- return INF_BAD
--- else
--- return floor((r * r * r + 0x20000) / 0x40000) -- 0400000 / 01000000
--- end
--- end
--- end
---
--- left-overs
---
--- local function round_xn_over_d(x, n, d)
--- local positive -- was x >= 0
--- if x >= 0 then
--- positive = true
--- else
--- x = -x
--- positive = false
--- end
--- local t = floor(x % 0x8000) * n -- 0100000
--- local f = floor(t / 0x8000) -- 0100000
--- local u = floor(x / 0x8000) * n + f -- 0100000
--- local v = floor(u % d) * 0x8000 + f -- 0100000
--- if floor(u / d) >= 0x8000 then -- 0100000
--- report_parbuilders('arith_error')
--- else
--- u = 0x8000 * floor(u / d) + floor(v / d) -- 0100000
--- end
--- v = floor(v % d)
--- if 2*v >= d then
--- u = u + 1
--- end
--- if positive then
--- return u
--- else
--- return -u
--- end
--- end
---
--- local function firstline(n)
--- while n do
--- local id = getid(n)
--- if id == hlist_code then
--- if getsubtype(n) == line_code then
--- return n
--- else
--- return firstline(getlist(n))
--- end
--- elseif id == vlist_code then
--- return firstline(getlist(n))
--- end
--- n = getnext(n)
--- end
--- end
---
--- nodes.firstline = firstline
-
function nuts.firstcharacter(n,untagged) -- tagged == subtype > 255
if untagged then
return first_glyph(n)
else
- for g in traverse_id(glyph_code,n) do
+ for g in nextglyph ,n do
return g
end
end
@@ -297,8 +207,8 @@ end
local function firstcharinbox(n)
local l = getlist(getbox(n))
if l then
- for g in traverse_id(glyph_code,l) do
- return getchar(g)
+ for g, c in nextglyph, l do
+ return c
end
end
return 0
@@ -431,10 +341,9 @@ nodes.link = function(list,currentfont,currentattr,head,tail)
end
local function locate(start,wantedid,wantedsubtype)
- for n in traverse_nodes(start) do
- local id = getid(n)
+ for n, id, subtype in nextnode, start do
if id == wantedid then
- if not wantedsubtype or getsubtype(n) == wantedsubtype then
+ if not wantedsubtype or subtype == wantedsubtype then
return n
end
elseif id == hlist_code or id == vlist_code then
@@ -490,87 +399,6 @@ end
-- end
-- end
--- these component helpers might move to another module
-
--- nodemode helper: here we also flatten components, no check for disc here
-
-function nuts.set_components(target,start,stop)
- local head = getcomponents(target)
- if head then
- flush_list(head)
- head = nil
- end
- if start then
- setprev(start)
- else
- return nil
- end
- if stop then
- setnext(stop)
- end
- local tail = nil
- while start do
- local c = getcomponents(start)
- local n = getnext(start)
- if c then
- if head then
- setlink(tail,c)
- else
- head = c
- end
- tail = find_tail(c)
- setcomponents(start)
- flush_node(start)
- else
- if head then
- setlink(tail,start)
- else
- head = start
- end
- tail = start
- end
- start = n
- end
- setcomponents(target,head)
- -- maybe also upgrade the subtype but we don't use it anyway
- return head
-end
-
-function nuts.get_components(target)
- return getcomponents(target)
-end
-
-nuts.get_components = getcomponents
-
-function nuts.take_components(target)
- local c = getcomponents(target)
- setcomponents(target)
- -- maybe also upgrade the subtype but we don't use it anyway
- return c
-end
-
--- nodemode helper: we assume a glyph and a flat components list (basemode can
--- have nested components)
-
-function nuts.count_components(n,marks)
- local components = getcomponents(n)
- if components then
- if marks then
- local i = 0
- for g in traverse_id(glyph_code,components) do
- if not marks[getchar(g)] then
- i = i + 1
- end
- end
- return i
- else
- return count(glyph_code,components)
- end
- else
- return 0
- end
-end
-
-- nodemode helper: the next and prev pointers are untouched
function nuts.copy_no_components(g,copyinjection)
@@ -596,7 +424,7 @@ end
function nuts.copy_only_glyphs(current)
local head = nil
local previous = nil
- for n in traverse_id(glyph_code,current) do
+ for n in nextglyph, current do
n = copy_node(n)
if head then
setlink(previous,n)
diff --git a/tex/context/base/mkiv/node-bck.lua b/tex/context/base/mkiv/node-bck.lua
index 4ed5abe5e..a19e5e969 100644
--- a/tex/context/base/mkiv/node-bck.lua
+++ b/tex/context/base/mkiv/node-bck.lua
@@ -9,178 +9,288 @@ if not modules then modules = { } end modules ['node-bck'] = {
-- beware, this one takes quite some runtime, so we need a status flag
-- maybe some page related state
+-- todo: done (or just get rid of done altogether) ... saves no purpose
+-- any longer
+
local attributes, nodes, node = attributes, nodes, node
-local enableaction = nodes.tasks.enableaction
+local enableaction = nodes.tasks.enableaction
-local nodecodes = nodes.nodecodes
-local listcodes = nodes.listcodes
+local nodecodes = nodes.nodecodes
+local listcodes = nodes.listcodes
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local cell_code = listcodes.cell
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
-local nuts = nodes.nuts
-local nodepool = nuts.pool
+local alignmentlist_code = listcodes.alignment
+local celllist_code = listcodes.cell
-local tonode = nuts.tonode
-local tonut = nuts.tonut
+local nuts = nodes.nuts
+local nodepool = nuts.pool
-local getnext = nuts.getnext
-local getprev = nuts.getprev
-local getid = nuts.getid
-local getlist = nuts.getlist
-local getattr = nuts.getattr
-local getsubtype = nuts.getsubtype
-local getwhd = nuts.getwhd
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getattr = nuts.getattr
+local getsubtype = nuts.getsubtype
+local getwhd = nuts.getwhd
+local getwidth = nuts.getwidth
+local getprop = nuts.getprop
-local setattr = nuts.setattr
-local setlink = nuts.setlink
-local setlist = nuts.setlist
+local setattr = nuts.setattr
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setattributelist = nuts.setattributelist
+local setprop = nuts.setprop
-local traverse = nuts.traverse
-local traverse_id = nuts.traverse_id
+local takebox = nuts.takebox
+local findtail = nuts.tail
-local new_rule = nodepool.rule
-local new_glue = nodepool.glue
+local nextnode = nuts.traversers.node
+local nexthlist = nuts.traversers.hlist
+local nextlist = nuts.traversers.list
-local a_color = attributes.private('color')
-local a_transparency = attributes.private('transparency')
-local a_colormodel = attributes.private('colormodel')
-local a_background = attributes.private('background')
-local a_alignbackground = attributes.private('alignbackground')
+local flush_node_list = nuts.flush_list
-local function add_backgrounds(head) -- rather old code .. to be redone
- local current = head
- while current do
- local id = getid(current)
- if id == hlist_code or id == vlist_code then
- local list = getlist(current)
- if list then
- local head = add_backgrounds(list)
- if head then
- setlist(current,head)
- list = head
- end
+local new_rule = nodepool.rule
+local new_kern = nodepool.kern
+local new_hlist = nodepool.hlist
+
+local privateattributes = attributes.private
+local unsetvalue = attributes.unsetvalue
+
+local linefillers = nodes.linefillers
+
+local a_color = privateattributes("color")
+local a_transparency = privateattributes("transparency")
+local a_colormodel = privateattributes("colormodel")
+local a_background = privateattributes("background")
+local a_alignbackground = privateattributes("alignbackground")
+local a_linefiller = privateattributes("linefiller")
+local a_ruled = privateattributes("ruled")
+
+local trace_alignment = false
+local report_alignment = logs.reporter("backgrounds","alignment")
+
+trackers.register("backgrounds.alignments",function(v) trace_alignment = v end)
+
+-- We can't use listbuilders with where=alignment because at that stage we have
+-- unset boxes. Also, post_linebreak is unsuitable for nested processing as we
+-- get the same stuff many times (wrapped again and again).
+--
+-- After many experiments with different callbacks the shipout is still the best
+-- place but then we need to store some settings longer or save them with the node.
+-- For color only we can get away with it with an extra attribute flagging a row
+-- but for more complex stuff we can better do as we do here now.
+
+local overshoot = math.floor(65781/5) -- could be an option per table (just also store it)
+
+local function colored_a(current,list,template,id)
+ local width, height, depth = getwhd(current)
+ local total = height + depth
+ if width > 0 and total > 0 then
+ local rule = nil
+ --
+ local a = getattr(template,a_linefiller)
+ if a then
+ local d = linefillers.data[a%1000]
+ if d then
+ rule = linefillers.filler(template,d,width,height,depth)
+ end
+ end
+ --
+ if not rule then
+ rule = new_rule(width,height,depth)
+ end
+ setattributelist(rule,template)
+ local back = new_kern(-((id == vlist_code and total) or width))
+ return setlink(rule,back,list)
+ end
+end
+
+local function colored_b(current,list,template,id,indent)
+ local width, height, depth = getwhd(current)
+ local total = height + depth
+ if width > 0 and total > 0 then
+ local fore = (indent ~= 0) and new_kern(indent)
+ local rule = nil
+ --
+ local a = getattr(template,a_linefiller)
+ if a then
+ local d = linefillers.data[a%1000]
+ if d then
+ rule = linefillers.filler(template,d,width-indent,height,depth)
end
- local width, height, depth = getwhd(current)
- if width > 0 then
- local background = getattr(current,a_background)
+ end
+ --
+ if not rule then
+ rule = new_rule(width-indent,height+overshoot,depth+overshoot)
+ setattributelist(rule,template)
+ end
+ if overshoot == 0 then
+ local back = new_kern(-((id == vlist_code and total) or width))
+ return setlink(fore,rule,back,list)
+ else
+ rule = new_hlist(rule)
+ return setlink(fore,rule,list)
+ end
+ end
+end
+
+local templates = { }
+local currentrow = 0
+local enabled = false
+local alignments = false
+
+local function add_alignbackgrounds(head,list)
+ for current, id, subtype, list in nextlist, list do
+ if list and id == hlist_code and subtype == celllist_code then
+ for template in nexthlist, list do
+ local background = getattr(template,a_alignbackground)
if background then
- -- direct to hbox
- -- colorspace is already set so we can omit that and stick to color
- local mode = getattr(current,a_colormodel)
- if mode then
- local skip = id == hlist_code and width or (height + depth)
- local glue = new_glue(-skip)
- local rule = new_rule(width,height,depth)
- local color = getattr(current,a_color)
- local transparency = getattr(current,a_transparency)
- setattr(rule,a_colormodel,mode)
- if color then
- setattr(rule,a_color,color)
- end
- if transparency then
- setattr(rule,a_transparency,transparency)
- end
--- setlink(rule,glue)
--- if list then
--- setlink(glue,list)
--- end
--- setlist(current,rule)
- setlist(current,rule,glue,list)
+ local list = colored_a(current,list,template)
+ if list then
+ setlist(current,list)
end
+ setattr(template,a_alignbackground,unsetvalue) -- or property
end
+ break
end
end
- current = getnext(current)
end
- return head, true
+ local template = getprop(head,"alignmentchecked")
+ if template then
+ list = colored_b(head,list,template[1],hlist_code,template[2])
+ flush_node_list(template)
+ templates[currentrow] = false
+ return list
+ end
end
-local function add_alignbackgrounds(head)
- local current = head
- while current do
- local id = getid(current)
- if id == hlist_code then
- local list = getlist(current)
- if not list then
- -- no need to look
- elseif getsubtype(current) == cell_code then
- local background = nil
- local found = nil
- -- for l in traverse(list) do
- -- background = getattr(l,a_alignbackground)
- -- if background then
- -- found = l
- -- break
- -- end
- -- end
- -- we know that it's a fake hlist (could be user node)
- -- but we cannot store tables in user nodes yet
- for l in traverse_id(hpack_code,list) do
- background = getattr(l,a_alignbackground)
- if background then
- found = l
+local function add_backgrounds(head,id,list)
+ if list then
+ for current, id, subtype, list in nextlist, list do
+ if list then
+ if alignments and subtype == alignmentlist_code then
+ local l = add_alignbackgrounds(current,list)
+ if l then
+ list = l
+ setlist(current,list)
end
- break
end
- --
- if background then
- -- current has subtype 5 (cell)
- local width, height, depth = getwhd(current)
- if width > 0 then
- local mode = getattr(found,a_colormodel)
- if mode then
- local glue = new_glue(-width)
- local rule = new_rule(width,height,depth)
- local color = getattr(found,a_color)
- local transparency = getattr(found,a_transparency)
- setattr(rule,a_colormodel,mode)
- if color then
- setattr(rule,a_color,color)
- end
- if transparency then
- setattr(rule,a_transparency,transparency)
- end
- setlink(rule,glue)
- if list then
- setlink(glue,list)
- end
- setlist(current,rule)
- end
- end
+ local l = add_backgrounds(current,id,list)
+ if l then
+ list = l
+ setlist(current,l)
end
- else
- add_alignbackgrounds(list)
end
- elseif id == vlist_code then
- local list = getlist(current)
- if list then
- add_alignbackgrounds(list)
+ end
+ end
+ if id == hlist_code or id == vlist_code then
+ local background = getattr(head,a_background)
+ if background then
+ list = colored_a(head,list,head,id)
+ -- not needed
+ setattr(head,a_background,unsetvalue) -- or property
+ return list
+ end
+ end
+end
+
+function nodes.handlers.backgrounds(head)
+ add_backgrounds(head,getid(head),getlist(head))
+ return head
+end
+
+function nodes.handlers.backgroundspage(head,where)
+ if head and where == "alignment" then
+ for n in nexthlist, head do
+ local p = getprop(n,"alignmentchecked")
+ if not p and getsubtype(n) == alignmentlist_code then
+ currentrow = currentrow + 1
+ local template = templates[currentrow]
+ if trace_alignment then
+ report_alignment("%03i %s %s",currentrow,"page",template and "+" or "-")
+ end
+ setprop(n,"alignmentchecked",template)
end
end
- current = getnext(current)
end
- return head, true
+ return head
end
--- nodes.handlers.backgrounds = add_backgrounds
--- nodes.handlers.alignbackgrounds = add_alignbackgrounds
+function nodes.handlers.backgroundsvbox(head,where)
+ if head and where == "vbox" then
+ local list = getlist(head)
+ if list then
+ for n in nexthlist, list do
+ local p = getprop(n,"alignmentchecked")
+ if not p and getsubtype(n) == alignmentlist_code then
+ currentrow = currentrow + 1
+ local template = templates[currentrow]
+ if trace_alignment then
+ report_alignment("%03i %s %s",currentrow,"vbox",template and "+" or "-")
+ end
+ setprop(n,"alignmentchecked",template)
+ end
+ end
+ end
+ end
+ return head
+end
-nodes.handlers.backgrounds = function(head) local head, done = add_backgrounds (tonut(head)) return tonode(head), done end
-nodes.handlers.alignbackgrounds = function(head) local head, done = add_alignbackgrounds(tonut(head)) return tonode(head), done end
+-- interfaces.implement {
+-- name = "enablebackgroundboxes",
+-- onlyonce = true,
+-- actions = enableaction,
+-- arguments = { "'shipouts'", "'nodes.handlers.backgrounds'" }
+-- }
+--
+-- doing it in the shipout works as well but this is nicer
+
+local function enable(alignmentstoo)
+ if not enabled then
+ enabled = true
+ enableaction("shipouts","nodes.handlers.backgrounds")
+ end
+ if not alignments and alignmentstoo then
+ alignments = true
+ enableaction("vboxbuilders","nodes.handlers.backgroundsvbox")
+ enableaction("mvlbuilders", "nodes.handlers.backgroundspage")
+ end
+end
interfaces.implement {
name = "enablebackgroundboxes",
onlyonce = true,
- actions = enableaction,
- arguments = { "'shipouts'", "'nodes.handlers.backgrounds'" }
+ actions = enable,
}
interfaces.implement {
name = "enablebackgroundalign",
onlyonce = true,
- actions = enableaction,
- arguments = { "'shipouts'", "'nodes.handlers.alignbackgrounds'" }
+ actions = function()
+ enable(true)
+ end,
+}
+
+interfaces.implement {
+ name = "setbackgroundrowdata",
+ arguments = { "integer", "integer", "dimension" },
+ actions = function(row,box,indent)
+ row = row -1 -- better here than in tex
+ if box == 0 then
+ templates[row] = false
+ else
+ templates[row] = { takebox(box), indent }
+ end
+ end,
+}
+
+interfaces.implement {
+ name = "resetbackgroundrowdata",
+ actions = function()
+ currentrow = 0
+ end,
}
diff --git a/tex/context/base/mkiv/node-bck.mkiv b/tex/context/base/mkiv/node-bck.mkiv
index 6bfc43d6a..b09327443 100644
--- a/tex/context/base/mkiv/node-bck.mkiv
+++ b/tex/context/base/mkiv/node-bck.mkiv
@@ -16,12 +16,10 @@
%D This is first attempt to replacing backgrounds in a few tables
%D mechanisms. When used more frequently, we can store the color
%D spec in the attribute.
-%D
-%D Maybe move some to the bar handler.
\unprotect
-\registerctxluafile{node-bck}{}
+\registerctxluafile{node-bck}{optimize}
% \backgroundvbox[green] {\input tufte } \par
% \backgroundvbox[blue] {\input ward } \par
@@ -74,6 +72,9 @@
\unexpanded\def\backgroundvbox{\node_backgrounds_boxes_add\vbox}
\unexpanded\def\backgroundvtop{\node_backgrounds_boxes_add\vtop}
+\unexpanded\def\backgroundline{\dontleavehmode
+ \node_backgrounds_boxes_add\hbox}
+
% \def\node_backgrounds_boxes_add#1[#2]%
% {\begingroup
% \clf_enablebackgroundboxes
@@ -90,18 +91,4 @@
{\clf_enablebackgroundboxes
#1\backgroundcolorattr{#2}}
-% less argument carry over:
-%
-% \def\node_backgrounds_boxes_add#1[#2]%
-% {\clf_enablebackgroundboxes#1%
-% \ifcsname\??colorattribute\currentcolorprefix#2\endcsname
-% \thebackgroundcolorattr{\currentcolorprefix#2}%
-% \else\ifcsname\??colorattribute#2\endcsname
-% \thebackgroundcolorattr{#2}%
-% \fi\fi}
-
-% \def\backgroundvbox[#1]{\vbox \backgroundcolorattr{#1}}
-% \def\backgroundvtop[#1]{\vtop \backgroundcolorattr{#1}}
-% \def\backgroundhbox[#1]{\hbox \backgroundcolorattr{#1}}
-
\protect \endinput
diff --git a/tex/context/base/mkiv/node-dir.lua b/tex/context/base/mkiv/node-dir.lua
index 59564ac93..3f0cba67e 100644
--- a/tex/context/base/mkiv/node-dir.lua
+++ b/tex/context/base/mkiv/node-dir.lua
@@ -6,304 +6,61 @@ if not modules then modules = { } end modules ['node-dir'] = {
license = "see context related readme files"
}
---[[
-<p>In the process of cleaning up the lua variant of the parbuilder
-we ran into a couple of functions (translated c macros) that were
-somewhat inefficient. More convenient is to use hashes although at
-the c-end still macros are used. In the process directions.h was
-adapted and now has the mappings as comments. This lua file is
-based on that file.
-]]--
-
-local allocate = utilities.storage.allocate
-
-local nodes = nodes
-
-nodes.is_mirrored = allocate {
- -- TLT = false,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
-}
-
-nodes.is_rotated = allocate { -- used
- -- TLT = false,
- -- TRT = false,
- -- LTL = false,
- RTT = true, ["+RTT"] = true,
-}
-
-nodes.textdir_is_parallel = allocate { -- used
- TLT = {
- TLT = true, ["+TLT"] = true,
- TRT = true, ["+TRT"] = true,
- -- LTL = false,
- -- RTT = false,
- },
- TRT= {
- TLT = true, ["+TLT"] = true,
- TRT = true, ["+TRT"] = true,
- -- LTL = false,
- -- RTT = false,
- },
- LTL = {
- -- TLT = false,
- -- TRT = false,
- LTL = true, ["+LTL"] = true,
- RTT = true, ["+RTT"] = true,
- },
- RTT = {
- -- TLT = false,
- -- TRT = false,
- LTL = true, ["+LTL"] = true,
- RTT = true, ["+RTT"] = true,
- }
-}
-
-nodes.pardir_is_parallel = allocate {
- TLT = {
- TLT = true, ["+TLT"] = true,
- TRT = true, ["+TRT"] = true,
- -- LTL = false,
- -- RTT = false,
- },
- TRT = {
- TLT = true, ["+TLT"] = true,
- TRT = true, ["+TRT"] = true,
- -- LTL = false,
- -- RTT = false,
- },
- LTL = {
- -- TLT = false,
- -- TRT = false,
- LTL = true, ["+LTL"] = true,
- RTT = true, ["+RTT"] = true,
- },
- RTT = {
- -- TLT = false,
- -- TRT = false,
- LTL = true, ["+LTL"] = true,
- RTT = true, ["+RTT"] = true,
- },
-}
-
-nodes.pardir_is_opposite = allocate {
- TLT = {
- -- TLT = false,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
- },
- TRT = {
- -- TLT = false,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
- },
- LTL = {
- -- TLT = false,
- -- TRT = false,
- -- LTL = false,
- RTT = true, ["+RTT"] = true,
- },
- RTT = {
- -- TLT = false,
- -- TRT = false,
- LTL = true, ["+LTL"] = true,
- -- RTT = false,
- },
-}
-
-nodes.textdir_is_opposite = allocate { -- used
- TLT = {
- -- TLT = false,
- TRT = true, ["+TRT"] = true,
- -- LTL = false,
- -- RTT = false,
- },
- TRT= {
- TLT = true, ["+TLT"] = true,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
- },
- LTL = {
- -- TLT = false,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
- },
- RTT = {
- -- TLT = false,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
- },
-}
-
-nodes.glyphdir_is_opposite = allocate {
- TLT = {
- -- TLT = false,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
- },
- TRT= {
- -- TLT = false,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
- },
- LTL = {
- -- TLT = false,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
- },
- RTT = {
- -- TLT = false,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
- },
-}
-
-nodes.pardir_is_equal = allocate { -- used
- TLT = {
- TLT = true, ["+TLT"] = true,
- TRT = true, ["+TRT"] = true,
- -- LTL = false,
- -- RTT = false,
- },
- TRT= {
- TLT = true, ["+TLT"] = true,
- TRT = true, ["+TRT"] = true,
- -- LTL = false,
- -- RTT = false,
- },
- LTL= {
- -- TLT = false,
- -- TRT = false,
- LTL = true, ["+LTL"] = true,
- -- RTT = false,
- },
- RTT= {
- -- TLT = false,
- -- TRT = false,
- -- LTL = false,
- RTT = true, ["+RTT"] = true,
- },
-}
-
-nodes.textdir_is_equal = allocate { -- used
- TLT = {
- TLT = true, ["+TLT"] = true,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
- },
- TRT= {
- -- TLT = false,
- TRT = true, ["+TRT"] = true,
- -- LTL = false,
- -- RTT = false,
- },
- LTL = {
- -- TLT = false,
- -- TRT = false,
- LTL = true, ["+LTL"] = true,
- RTT = true, ["+RTT"] = true,
- },
- RTT = {
- -- TLT = false,
- -- TRT = false,
- LTL = true, ["+LTL"] = true,
- RTT = true, ["+RTT"] = true,
- },
-}
-
-nodes.glyphdir_is_equal = allocate { -- used
- TLT = {
- TLT = true, ["+TLT"] = true,
- TRT = true, ["+TRT"] = true,
- -- LTL = false,
- RTT = true, ["+RTT"] = true,
- },
- TRT= {
- TLT = true, ["+TLT"] = true,
- TRT = true, ["+TRT"] = true,
- -- LTL = false,
- RTT = true, ["+RTT"] = true,
- },
- LTL = {
- -- TLT = false,
- -- TRT = false,
- LTL = true, ["+LTL"] = true,
- -- RTT = false,
- },
- RTT = {
- TLT = true, ["+TLT"] = true,
- TRT = true, ["+TRT"] = true,
- -- LTL = false,
- RTT = true, ["+RTT"] = true,
- },
-}
-
-nodes.partextdir_is_equal = allocate {
- TLT = {
- -- TLT = false,
- -- TRT = false,
- LTL = true, ["+LTL"] = true,
- RTT = true, ["+RTT"] = true,
- },
- TRT= {
- -- TLT = false,
- -- TRT = false,
- LTL = true, ["+LTL"] = true,
- RTT = true, ["+RTT"] = true,
- },
- LTL = {
- TLT = true, ["+TLT"] = true,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
- },
- RTT = {
- -- TLT = false,
- TRT = true, ["+TRT"] = true,
- -- LTL = false,
- -- RTT = false,
- },
-}
-
-nodes.textdir_is_is = allocate {
- TLT = true, ["+TLT"] = true,
- -- TRT = false,
- -- LTL = false,
- -- RTT = false,
-}
-
-nodes.glyphdir_is_orthogonal = allocate {
- TLT = true, ["+TLT"] = true,
- TRT = true, ["+TRT"] = true,
- LTL = true, ["+LTL"] = true,
- -- RTT = false
-}
-
-nodes.dir_is_pop = allocate { -- used
- ["-TRT"] = true,
- ["-TLT"] = true,
- ["-LTL"] = true,
- ["-RTT"] = true,
-}
-
-nodes.dir_negation = allocate { -- used
- ["-TRT"] = "+TRT",
- ["-TLT"] = "+TLT",
- ["-LTL"] = "+LTL",
- ["-RTT"] = "+RTT",
- ["+TRT"] = "-TRT",
- ["+TLT"] = "-TLT",
- ["+LTL"] = "-LTL",
- ["+RTT"] = "-RTT",
-}
+-- This is experimental code, so when I change it I need to check other modules
+-- too.
+--
+-- Local par nodes are somewhat special. They start a paragraph and then register
+-- the par direction. But they can also show op mid paragraph in which case they
+-- register boxes and penalties. In that case the direction should not be affected.
+--
+-- We can assume that when hpack and prelinebreak filters are called, a local par
+-- still sits at the head, but after a linebreak pass this node can be after the
+-- leftskip (when present).
+
+local nodes = nodes
+local nuts = nodes.nuts
+
+local nodecodes = nodes.nodecodes
+local localpar_code = nodecodes.localpar
+
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getdirection = nuts.getdirection
+
+local dirvalues = nodes.dirvalues
+local lefttoright = dirvalues.lefttoright
+local righttoleft = dirvalues.righttoleft
+
+local localparnewgraf_code = 0
+
+local function newstack(head,direction)
+ local stack = { }
+ local top = 0
+ if head and getid(head) == localpar_code and getsubtype(head) == localparnewgraf_code then
+ direction = getdirection(head)
+ end
+ if not direction then
+ direction = lefttoright
+ elseif direction == "TLT" then
+ direction = lefttoright
+ elseif direction == "TRT" then
+ direction = righttoleft
+ end
+ local function update(node)
+ local dir, pop = getdirection(node)
+ if not pop then
+ top = top + 1
+ stack[top] = dir
+ return dir
+ elseif top == 0 then
+ return direction
+ elseif top == 1 then
+ top = 0
+ return direction
+ else
+ top = top - 1
+ return stack[top]
+ end
+ end
+ return direction, update
+end
diff --git a/tex/context/base/mkiv/node-fin.lua b/tex/context/base/mkiv/node-fin.lua
index 975eb0bec..dc681d165 100644
--- a/tex/context/base/mkiv/node-fin.lua
+++ b/tex/context/base/mkiv/node-fin.lua
@@ -16,16 +16,15 @@ local next, type, format = next, type, string.format
local attributes, nodes, node = attributes, nodes, node
local nuts = nodes.nuts
-local tonode = nuts.tonode
-local tonut = nuts.tonut
local getnext = nuts.getnext
-local getprev = nuts.getprev
local getid = nuts.getid
local getlist = nuts.getlist
local getleader = nuts.getleader
local getattr = nuts.getattr
local getwidth = nuts.getwidth
+local getwhd = nuts.getwhd
+local getorientation = nuts.getorientation
local setlist = nuts.setlist
local setleader = nuts.setleader
@@ -34,10 +33,22 @@ local copy_node = nuts.copy
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
+local nextnode = nuts.traversers.node
+
local nodecodes = nodes.nodecodes
-local whatcodes = nodes.whatcodes
local rulecodes = nodes.rulecodes
+----- normalrule_code = rulecodes.normal
+local boxrule_code = rulecodes.box
+local imagerule_code = rulecodes.image
+local emptyrule_code = rulecodes.empty
+----- userrule_code = rulecodes.user
+----- overrule_code = rulecodes.over
+----- underrule_code = rulecodes.under
+----- fractionrule_code = rulecodes.fraction
+----- radicalrule_code = rulecodes.radical
+----- outlinerule_code = rulecodes.outline
+
local glyph_code = nodecodes.glyph
local disc_code = nodecodes.disc
local glue_code = nodecodes.glue
@@ -82,37 +93,34 @@ local finalizer = plugin.finalizer
local flusher = plugin.flusher
if not processor then
return function(head)
- return head, false
+ return head
end
elseif initializer or finalizer or resolver then
return function(head)
starttiming(attributes)
- local done, used, ok, inheritance = false, nil, false, nil
+ local used, inheritance
if resolver then
inheritance = resolver()
end
if initializer then
initializer(namespace,attribute,head)
end
- head, ok = processor(namespace,attribute,head,inheritance)
- if ok then
- if finalizer then
- head, ok, used = finalizer(namespace,attribute,head)
- if used and flusher then
- head = flusher(namespace,attribute,head,used)
- end
+ head = processor(namespace,attribute,head,inheritance)
+ if finalizer then
+ head, used = finalizer(namespace,attribute,head)
+ if used and flusher then
+ head = flusher(namespace,attribute,head,used)
end
- done = true
end
stoptiming(attributes)
- return head, done
+ return head
end
else
return function(head)
starttiming(attributes)
- local head, done = processor(namespace,attribute,head)
+ head = processor(namespace,attribute,head)
stoptiming(attributes)
- return head, done
+ return head
end
end
nodes.plugindata = nil
@@ -126,7 +134,7 @@ end
-- the injectors
local nsdata, nsnone, nslistwise, nsforced, nsselector, nstrigger
-local current, current_selector, done = 0, 0, false -- nb, stack has a local current !
+local current, current_selector = 0, 0 -- nb, stack has a local current !
local nsbegin, nsend, nsreset
function states.initialize(namespace,attribute,head)
@@ -138,7 +146,6 @@ function states.initialize(namespace,attribute,head)
nstrigger = triggering and namespace.triggering and a_trigger
current = 0
current_selector = 0
- done = false -- todo: done cleanup
nsstep = namespace.resolve_step
if nsstep then
nsreset = namespace.resolve_reset
@@ -151,7 +158,6 @@ end
function states.finalize(namespace,attribute,head) -- is this one ok?
if current > 0 and nsnone then
- head = tonut(head)
local id = getid(head)
if id == hlist_code or id == vlist_code then
local content = getlist(head)
@@ -164,20 +170,17 @@ function states.finalize(namespace,attribute,head) -- is this one ok?
else
head = insert_node_before(head,head,copy_node(nsnone))
end
- return tonode(head), true, true
+ return head, true
end
- return head, false, false
+ return head, false
end
-- we need to deal with literals too (reset as well as oval)
local function process(attribute,head,inheritance,default) -- one attribute
- local stack = head
- local done = false
local check = false
local leader = nil
- while stack do
- local id = getid(stack)
+ for stack, id in nextnode, head do
if id == glyph_code or id == disc_code then
check = true -- disc no longer needed as we flatten replace
elseif id == glue_code then
@@ -188,39 +191,52 @@ local function process(attribute,head,inheritance,default) -- one attribute
elseif id == hlist_code or id == vlist_code then
local content = getlist(stack)
if content then
+ -- tricky checking
+ local outer
+ if getorientation(stack) then
+ outer = getattr(stack,attribute)
+ if outer then
+ if default and outer == inheritance then
+ if current ~= default then
+ head = insert_node_before(head,stack,copy_node(nsdata[default]))
+ current = default
+ end
+ elseif current ~= outer then
+ head = insert_node_before(head,stack,copy_node(nsdata[c]))
+ current = outer
+ end
+ elseif default and inheritance then
+ if current ~= default then
+ head = insert_node_before(head,stack,copy_node(nsdata[default]))
+ current = default
+ end
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copy_node(nsnone))
+ current = 0
+ end
+ end
-- begin nested --
+ local list
if nstrigger and getattr(stack,nstrigger) then
- local outer = getattr(stack,attribute)
+ if not outer then
+ outer = getattr(stack,attribute)
+ end
if outer ~= inheritance then
- local list, ok = process(attribute,content,inheritance,outer)
- if content ~= list then
- setlist(stack,list)
- end
- if ok then
- done = true
- end
+ list = process(attribute,content,inheritance,outer)
else
- local list, ok = process(attribute,content,inheritance,default)
- if content ~= list then
- setlist(stack,list)
- end
- if ok then
- done = true
- end
+ list = process(attribute,content,inheritance,default)
end
else
- local list, ok = process(attribute,content,inheritance,default)
- if content ~= list then
- setlist(stack,list)
- end
- if ok then
- done = true
- end
+ list = process(attribute,content,inheritance,default)
+ end
+ if content ~= list then
+ setlist(stack,list)
end
-- end nested --
end
elseif id == rule_code then
- check = getwidth(stack) ~= 0
+ local wd, ht, dp = getwhd(stack)
+ check = wd ~= 0 or (ht+dp) ~= 0
end
-- much faster this way than using a check() and nested() function
if check then
@@ -230,12 +246,10 @@ local function process(attribute,head,inheritance,default) -- one attribute
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
if leader then
local savedcurrent = current
@@ -247,33 +261,19 @@ local function process(attribute,head,inheritance,default) -- one attribute
current = 0
end
-- begin nested --
+ local list
if nstrigger and getattr(stack,nstrigger) then
local outer = getattr(stack,attribute)
if outer ~= inheritance then
- local list, ok = process(attribute,leader,inheritance,outer)
- if leader ~= list then
- setleader(stack,list)
- end
- if ok then
- done = true
- end
+ list = process(attribute,leader,inheritance,outer)
else
- local list, ok = process(attribute,leader,inheritance,default)
- if leader ~= list then
- setleader(stack,list)
- end
- if ok then
- done = true
- end
+ list = process(attribute,leader,inheritance,default)
end
else
- local list, ok = process(attribute,leader,inheritance,default)
- if leader ~= list then
- setleader(stack,list)
- end
- if ok then
- done = true
- end
+ list = process(attribute,leader,inheritance,default)
+ end
+ if leader ~= list then
+ setleader(stack,list)
end
-- end nested --
current = savedcurrent
@@ -283,23 +283,19 @@ local function process(attribute,head,inheritance,default) -- one attribute
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
check = false
end
- stack = getnext(stack)
end
- return head, done
+ return head
end
states.process = function(namespace,attribute,head,default)
- local head, done = process(attribute,tonut(head),default)
- return tonode(head), done
+ return process(attribute,head,default)
end
-- we can force a selector, e.g. document wide color spaces, saves a little
@@ -309,13 +305,9 @@ end
-- each other with the same color but different color spaces e.g. \showcolor)
local function selective(attribute,head,inheritance,default) -- two attributes
- -- local head = head
- local stack = head
- local done = false
local check = false
local leader = nil
- while stack do
- local id = getid(stack)
+ for stack, id, subtype in nextnode, head do
if id == glyph_code or id == disc_code then
check = true -- disc no longer needed as we flatten replace
elseif id == glue_code then
@@ -326,41 +318,66 @@ local function selective(attribute,head,inheritance,default) -- two attributes
elseif id == hlist_code or id == vlist_code then
local content = getlist(stack)
if content then
+ -- tricky checking
+ local outer
+ if getorientation(stack) then
+ outer = getattr(stack,attribute)
+ if outer then
+ if default and outer == inheritance then
+ if current ~= default then
+ local data = nsdata[default]
+ head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(stack,nsselector) or nsselector]))
+ current = default
+ end
+ else
+ local s = getattr(stack,nsselector)
+ -- local s = nsforced or getattr(stack,nsselector)
+ if current ~= outer or current_selector ~= s then
+ local data = nsdata[outer]
+ head = insert_node_before(head,stack,copy_node(data[nsforced or s or nsselector]))
+ current = outer
+ current_selector = s
+ 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 getattr(stack,nsselector) or nsselector]))
+ current = default
+ end
+ elseif current > 0 then
+ head = insert_node_before(head,stack,copy_node(nsnone))
+ current, current_selector = 0, 0
+ end
+ end
-- begin nested
+ local list
if nstrigger and getattr(stack,nstrigger) then
- local outer = getattr(stack,attribute)
+ if not outer then
+ outer = getattr(stack,attribute)
+ end
if outer ~= inheritance then
- local list, ok = selective(attribute,content,inheritance,outer)
- if content ~= list then
- setlist(stack,list)
- end
- if ok then
- done = true
- end
+ list = selective(attribute,content,inheritance,outer)
else
- local list, ok = selective(attribute,content,inheritance,default)
- if content ~= list then
- setlist(stack,list)
- end
- if ok then
- done = true
- end
+ list = selective(attribute,content,inheritance,default)
end
else
- local list, ok = selective(attribute,content,inheritance,default)
- if content ~= list then
- setlist(stack,list)
- end
- if ok then
- done = true
- end
+ list = selective(attribute,content,inheritance,default)
+ end
+ if content ~= list then
+ setlist(stack,list)
end
-- end nested
end
elseif id == rule_code then
- check = getwidth(stack) ~= 0
+ if subtype == boxrule_code or subtype == imagerule_code or subtype == emptyrule_code then
+ -- so no redundant color stuff (only here, layers for instance should obey)
+ check = false
+ else
+ local wd, ht, dp = getwhd(stack)
+ check = wd ~= 0 or (ht+dp) ~= 0
+ end
end
-
if check then
local c = getattr(stack,attribute)
if c then
@@ -369,9 +386,6 @@ local function selective(attribute,head,inheritance,default) -- two attributes
local data = nsdata[default]
head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(stack,nsselector) or nsselector]))
current = default
- if ok then
- done = true
- end
end
else
local s = getattr(stack,nsselector)
@@ -379,43 +393,25 @@ local function selective(attribute,head,inheritance,default) -- two attributes
if current ~= c or current_selector ~= s then
local data = nsdata[c]
head = insert_node_before(head,stack,copy_node(data[nsforced or s or nsselector]))
- -- head = insert_node_before(head,stack,copy_node(data[s or nsselector]))
current = c
current_selector = s
- if ok then
- done = true
- end
end
end
if leader then
-- begin nested
+ local list
if nstrigger and getattr(stack,nstrigger) then
local outer = getattr(stack,attribute)
if outer ~= inheritance then
- local list, ok = selective(attribute,leader,inheritance,outer)
- if leader ~= list then
- setleader(stack,list)
- end
- if ok then
- done = true
- end
+ list = selective(attribute,leader,inheritance,outer)
else
- local list, ok = selective(attribute,leader,inheritance,default)
- if leader ~= list then
- setleader(stack,list)
- end
- if ok then
- done = true
- end
+ list = selective(attribute,leader,inheritance,default)
end
else
- local list, ok = selective(attribute,leader,inheritance,default)
- if leader ~= list then
- setleader(stack,list)
- end
- if ok then
- done = true
- end
+ list = selective(attribute,leader,inheritance,default)
+ end
+ if leader ~= list then
+ setleader(stack,list)
end
-- end nested
leader = false
@@ -425,22 +421,19 @@ local function selective(attribute,head,inheritance,default) -- two attributes
local data = nsdata[default]
head = insert_node_before(head,stack,copy_node(data[nsforced or getattr(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
+ current, current_selector = 0, 0
end
check = false
end
- stack = getnext(stack)
end
- return head, done
+ return head
end
states.selective = function(namespace,attribute,head,default)
- local head = selective(attribute,tonut(head),default)
- return tonode(head), true
+ return selective(attribute,head,default)
end
-- Ideally the next one should be merged with the previous but keeping it separate is
@@ -454,7 +447,6 @@ end
local function stacked(attribute,head,default) -- no triggering, no inheritance, but list-wise
local stack = head
- local done = false
local current = default or 0
local depth = 0
local check = false
@@ -472,42 +464,30 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance,
local content = getlist(stack)
if content then
-- the problem is that broken lines gets the attribute which can be a later one
+ local list
if nslistwise then
local a = getattr(stack,attribute)
if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below
local p = current
current = a
head = insert_node_before(head,stack,copy_node(nsdata[a]))
- local list = stacked(attribute,content,current) -- two return values
- if content ~= list then
- setlist(stack,list)
- end
+ list = stacked(attribute,content,current) -- two return values
head, stack = insert_node_after(head,stack,copy_node(nsnone))
current = p
- done = true
else
- local list, ok = stacked(attribute,content,current)
- if content ~= list then
- setlist(stack,list) -- only if ok
- end
- if ok then
- done = true
- end
+ list = stacked(attribute,content,current)
end
else
- local list, ok = stacked(attribute,content,current)
- if content ~= list then
- setlist(stack,list) -- only if ok
- end
- if ok then
- done = true
- end
+ list = stacked(attribute,content,current)
+ end
+ if content ~= list then
+ setlist(stack,list) -- only if ok
end
end
elseif id == rule_code then
- check = getwidth(stack) ~= 0
+ local wd, ht, dp = getwhd(stack)
+ check = wd ~= 0 or (ht+dp) ~= 0
end
-
if check then
local a = getattr(stack,attribute)
if a then
@@ -515,15 +495,14 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance,
head = insert_node_before(head,stack,copy_node(nsdata[a]))
depth = depth + 1
current = a
- done = true
end
if leader then
- local list, ok = stacked(attribute,content,current)
- if leader ~= list then
- setleader(stack,list) -- only if ok
- end
- if ok then
- done = true
+ local content = getlist(leader)
+ if content then
+ local list = stacked(attribute,content,current)
+ if leader ~= list then
+ setleader(stack,list) -- only if ok
+ end
end
leader = false
end
@@ -533,7 +512,6 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance,
head = insert_node_before(head,stack,copy_node(nsnone))
depth = depth - 1
current = 0
- done = true
end
check = false
end
@@ -543,24 +521,22 @@ local function stacked(attribute,head,default) -- no triggering, no inheritance,
head = insert_node_after(head,stack,copy_node(nsnone))
depth = depth - 1
end
- return head, done
+ return head
end
states.stacked = function(namespace,attribute,head,default)
- local head, done = stacked(attribute,tonut(head),default)
- return tonode(head), done
+ return stacked(attribute,head,default)
end
-- experimental
local function stacker(attribute,head,default) -- no triggering, no inheritance, but list-wise
--- nsbegin()
+ -- nsbegin()
local stacked = false
local current = head
local previous = head
- local done = false
local attrib = default or unsetvalue
local check = false
local leader = false
@@ -576,38 +552,27 @@ local function stacker(attribute,head,default) -- no triggering, no inheritance,
end
elseif id == hlist_code or id == vlist_code then
local content = getlist(current)
- if not content then
- -- skip
- elseif nslistwise then
- local a = getattr(current,attribute)
- if a and attrib ~= a and nslistwise[a] then -- viewerlayer
- head = insert_node_before(head,current,copy_node(nsdata[a]))
- local list = stacker(attribute,content,a)
- if list ~= content then
- setlist(current,list)
+ if content then
+ local list
+ if nslistwise then
+ local a = getattr(current,attribute)
+ if a and attrib ~= a and nslistwise[a] then -- viewerlayer
+ head = insert_node_before(head,current,copy_node(nsdata[a]))
+ list = stacker(attribute,content,a)
+ head, current = insert_node_after(head,current,copy_node(nsnone))
+ else
+ list = stacker(attribute,content,attrib)
end
- done = true
- head, current = insert_node_after(head,current,copy_node(nsnone))
else
- local list, ok = stacker(attribute,content,attrib)
- if content ~= list then
- setlist(current,list)
- end
- if ok then
- done = true
- end
+ list = stacker(attribute,content,default)
end
- else
- local list, ok = stacker(attribute,content,default)
if list ~= content then
setlist(current,list)
end
- if ok then
- done = true
- end
end
elseif id == rule_code then
- check = getwidth(current) ~= 0
+ local wd, ht, dp = getwhd(current)
+ check = wd ~= 0 or (ht+dp) ~= 0
end
if check then
@@ -619,16 +584,22 @@ local function stacker(attribute,head,default) -- no triggering, no inheritance,
end
local n = nsstep(a)
if n then
- head = insert_node_before(head,current,tonut(n)) -- a
+ head = insert_node_before(head,current,n) -- a
end
attrib = a
- done = true
if leader then
-- tricky as a leader has to be a list so we cannot inject before
- local list, ok = stacker(attribute,leader,attrib)
- if ok then
- done = true
+ -- local list = stacker(attribute,leader,attrib)
+ -- leader = false
+
+ local content = getlist(leader)
+ if content then
+ local list = stacker(attribute,leader,attrib)
+ if leader ~= list then
+ setleader(current,list)
+ end
end
+
leader = false
end
end
@@ -642,18 +613,101 @@ local function stacker(attribute,head,default) -- no triggering, no inheritance,
if stacked then
local n = nsend()
while n do
- head = insert_node_after(head,previous,tonut(n))
+ head = insert_node_after(head,previous,n)
n = nsend()
end
end
- return head, done
+ return head
end
+-- local nextid = nodes.nuts.traversers.id
+--
+-- local function stacker(attribute,head,default) -- no triggering, no inheritance, but list-wise
+--
+-- -- nsbegin()
+-- local stacked = false
+--
+-- local current = head
+-- local previous = head
+-- local attrib = default or unsetvalue
+-- local check = false
+-- local leader = false
+--
+-- local id = getid(current)
+-- while current do
+-- if id == glyph_code then
+-- check = true
+-- elseif id == glue_code then
+-- leader = getleader(current)
+-- if leader then
+-- check = true
+-- end
+-- elseif id == hlist_code or id == vlist_code then
+-- local content = getlist(current)
+-- if content then
+-- local list
+-- if nslistwise then
+-- local a = getattr(current,attribute)
+-- if a and attrib ~= a and nslistwise[a] then -- viewerlayer
+-- head = insert_node_before(head,current,copy_node(nsdata[a]))
+-- list = stacker(attribute,content,a)
+-- head, current = insert_node_after(head,current,copy_node(nsnone))
+-- else
+-- list = stacker(attribute,content,attrib)
+-- end
+-- else
+-- list = stacker(attribute,content,default)
+-- end
+-- if list ~= content then
+-- setlist(current,list)
+-- end
+-- end
+-- elseif id == rule_code then
+-- check = getwidth(current) ~= 0
+-- end
+--
+-- if check then
+-- local a = getattr(current,attribute) or unsetvalue
+-- if a ~= attrib then
+-- if not stacked then
+-- stacked = true
+-- nsbegin()
+-- end
+-- local n = nsstep(a)
+-- if n then
+-- head = insert_node_before(head,current,n) -- a
+-- end
+-- attrib = a
+-- if leader then
+-- -- tricky as a leader has to be a list so we cannot inject before
+-- local list = stacker(attribute,leader,attrib)
+-- leader = false
+-- end
+-- end
+-- check = false
+-- end
+--
+-- previous = current
+--
+-- current, id = nextid(current,current)
+-- end
+--
+-- if stacked then
+-- local n = nsend()
+-- while n do
+-- head = insert_node_after(head,previous,n)
+-- n = nsend()
+-- end
+-- end
+--
+-- return head
+-- end
+
states.stacker = function(namespace,attribute,head,default)
- local head, done = stacker(attribute,tonut(head),default)
+ local head = stacker(attribute,head,default)
nsreset()
- return tonode(head), done
+ return head
end
-- -- --
diff --git a/tex/context/base/mkiv/node-fin.mkiv b/tex/context/base/mkiv/node-fin.mkiv
index 4f1ff2aba..086b19ae5 100644
--- a/tex/context/base/mkiv/node-fin.mkiv
+++ b/tex/context/base/mkiv/node-fin.mkiv
@@ -18,8 +18,8 @@
\unprotect
-\registerctxluafile{node-shp}{}
-\registerctxluafile{node-fin}{} % we might generalize this one
+\registerctxluafile{node-shp}{optimize}
+\registerctxluafile{node-fin}{optimize} % we might generalize this one
% we might have two variants at some point (efficiency)
diff --git a/tex/context/base/mkiv/node-fnt.lua b/tex/context/base/mkiv/node-fnt.lua
index f846f996d..154853121 100644
--- a/tex/context/base/mkiv/node-fnt.lua
+++ b/tex/context/base/mkiv/node-fnt.lua
@@ -37,22 +37,20 @@ local starttiming = statistics.starttiming
local stoptiming = statistics.stoptiming
local nodecodes = nodes.nodecodes
+local boundarycodes = nodes.boundarycodes
+
local handlers = nodes.handlers
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local getattr = nuts.getattr
local getid = nuts.getid
-local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
-local getchar = nuts.getchar
local getdisc = nuts.getdisc
local getnext = nuts.getnext
local getprev = nuts.getprev
local getboth = nuts.getboth
-local getfield = nuts.getfield
+local getdata = nuts.getdata
----- getdisc = nuts.getdisc
local setchar = nuts.setchar
local setlink = nuts.setlink
@@ -62,14 +60,18 @@ local setprev = nuts.setprev
local isglyph = nuts.isglyph -- unchecked
local ischar = nuts.ischar -- checked
-local traverse_id = nuts.traverse_id
-local traverse_char = nuts.traverse_char
-local protect_glyph = nuts.protect_glyph
+----- traverse_id = nuts.traverse_id
+----- traverse_char = nuts.traverse_char
+local nextboundary = nuts.traversers.boundary
+local nextdisc = nuts.traversers.disc
+local nextchar = nuts.traversers.char
+
local flush_node = nuts.flush
local disc_code = nodecodes.disc
local boundary_code = nodecodes.boundary
-local word_boundary = nodes.boundarycodes.word
+
+local wordboundary_code = boundarycodes.word
local protect_glyphs = nuts.protect_glyphs
local unprotect_glyphs = nuts.unprotect_glyphs
@@ -144,10 +146,10 @@ local kerning = nuts.kerning
-- -- -- this will go away
--
--- local disccodes = nodes.disccodes
--- local explicit_code = disccodes.explicit
--- local automatic_code = disccodes.automatic
--- local expanders = nil
+-- local disccodes = nodes.disccodes
+-- local explicitdisc_code = disccodes.explicit
+-- local automaticdisc_code = disccodes.automatic
+-- local expanders = nil
--
-- function fonts.setdiscexpansion(v)
-- if v == nil or v == true then
@@ -172,17 +174,17 @@ local function start_trace(head)
report_fonts()
report_fonts("checking node list, run %s",run)
report_fonts()
- local n = tonut(head)
+ local n = head
while n do
local char, id = isglyph(n)
if char then
- local font = getfont(n)
+ local font = id
local attr = getattr(n,0) or 0
report_fonts("font %03i, dynamic %03i, glyph %C",font,attr,char)
elseif id == disc_code then
report_fonts("[disc] %s",nodes.listtoutf(n,true,false,n))
elseif id == boundary_code then
- report_fonts("[boundary] %i:%i",getsubtype(n),getfield(n,"value"))
+ report_fonts("[boundary] %i:%i",getsubtype(n),getdata(n))
else
report_fonts("[%s]",nodecodes[id])
end
@@ -202,32 +204,23 @@ local function stop_trace(u,usedfonts,a,attrfonts,b,basefonts,r,redundant,e,expa
report_fonts()
end
-function handlers.characters(head,groupcode,size,packtype,direction)
- -- either next or not, but definitely no already processed list
- starttiming(nodes)
-
- local usedfonts = { }
- local attrfonts = { }
- local basefonts = { }
- local basefont = nil
- local prevfont = nil
- local prevattr = 0
- local done = false
- local variants = nil
- local redundant = nil
- local nuthead = tonut(head)
- local lastfont = nil
- local lastproc = nil
- local lastnone = nil
-
- local a, u, b, r, e = 0, 0, 0, 0, 0
-
- if trace_fontrun then
- start_trace(head)
- end
- -- There is no gain in checking for a single glyph and then having a fast path. On the
- -- metafun manual (with some 2500 single char lists) the difference is just noise.
+do
+
+ local usedfonts
+ local attrfonts
+ local basefonts
+ local basefont
+ local prevfont
+ local prevattr
+ local variants
+ local redundant
+ local firstnone
+ local lastfont
+ local lastproc
+ local lastnone
+
+ local a, u, b, r, e
local function protectnone()
protect_glyphs(firstnone,lastnone)
@@ -296,288 +289,290 @@ function handlers.characters(head,groupcode,size,packtype,direction)
end
end
- for n in traverse_char(nuthead) do
- local font = getfont(n)
- -- local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
- local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
- if font ~= prevfont or attr ~= prevattr then
- prevfont = font
- prevattr = attr
- variants = fontvariants[font]
- local fontmode = fontmodes[font]
- if fontmode == "none" then
- setnone(n)
- elseif fontmode == "base" then
- setbase(n)
- else
- setnode(n,font,attr)
- end
- elseif firstnone then
- lastnone = n
+ function handlers.characters(head,groupcode,size,packtype,direction)
+ -- either next or not, but definitely no already processed list
+ starttiming(nodes)
+
+ usedfonts = { }
+ attrfonts = { }
+ basefonts = { }
+ basefont = nil
+ prevfont = nil
+ prevattr = 0
+ variants = nil
+ redundant = nil
+ firstnone = nil
+ lastfont = nil
+ lastproc = nil
+ lastnone = nil
+
+ a, u, b, r, e = 0, 0, 0, 0, 0
+
+ if trace_fontrun then
+ start_trace(head)
end
- if variants then
- local char = getchar(n)
- if char >= 0xFE00 and (char <= 0xFE0F or (char >= 0xE0100 and char <= 0xE01EF)) then
- local hash = variants[char]
- if hash then
- local p = getprev(n)
- if p then
- local char = ischar(p) -- checked
- local variant = hash[char]
- if variant then
- if trace_variants then
- report_fonts("replacing %C by %C",char,variant)
- end
- setchar(p,variant)
- if redundant then
- r = r + 1
- redundant[r] = n
- else
- r = 1
- redundant = { n }
+
+ -- There is no gain in checking for a single glyph and then having a fast path. On the
+ -- metafun manual (with some 2500 single char lists) the difference is just noise.
+
+ for n, char, font in nextchar, head do
+ -- local attr = (none and prevattr) or getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
+ local attr = getattr(n) or 0 -- zero attribute is reserved for fonts in context
+ if font ~= prevfont or attr ~= prevattr then
+ prevfont = font
+ prevattr = attr
+ variants = fontvariants[font]
+ local fontmode = fontmodes[font]
+ if fontmode == "none" then
+ setnone(n)
+ elseif fontmode == "base" then
+ setbase(n)
+ else
+ setnode(n,font,attr)
+ end
+ elseif firstnone then
+ lastnone = n
+ end
+ if variants then
+ if (char >= 0xFE00 and char <= 0xFE0F) or (char >= 0xE0100 and char <= 0xE01EF) then
+ local hash = variants[char]
+ if hash then
+ local p = getprev(n)
+ if p then
+ local char = ischar(p) -- checked
+ local variant = hash[char]
+ if variant then
+ if trace_variants then
+ report_fonts("replacing %C by %C",char,variant)
+ end
+ setchar(p,variant)
+ if redundant then
+ r = r + 1
+ redundant[r] = n
+ else
+ r = 1
+ redundant = { n }
+ end
end
end
+ elseif keep_redundant then
+ -- go on, can be used for tracing
+ elseif redundant then
+ r = r + 1
+ redundant[r] = n
+ else
+ r = 1
+ redundant = { n }
end
- elseif keep_redundant then
- -- go on, can be used for tracing
- elseif redundant then
- r = r + 1
- redundant[r] = n
- else
- r = 1
- redundant = { n }
end
end
end
- end
- if firstnone then
- protectnone()
- end
+ if firstnone then
+ protectnone()
+ end
- if force_boundaryrun then
+ if force_boundaryrun then
- -- we can inject wordboundaries and then let the hyphenator do its work
- -- but we need to get rid of those nodes in order to build ligatures
- -- and kern (a rather context thing)
+ -- we can inject wordboundaries and then let the hyphenator do its work
+ -- but we need to get rid of those nodes in order to build ligatures
+ -- and kern (a rather context thing)
- for b in traverse_id(boundary_code,nuthead) do
- if getsubtype(b) == word_boundary then
- if redundant then
- r = r + 1
- redundant[r] = b
- else
- r = 1
- redundant = { b }
+ for b, subtype in nextboundary, head do
+ if subtype == wordboundary_code then
+ if redundant then
+ r = r + 1
+ redundant[r] = b
+ else
+ r = 1
+ redundant = { b }
+ end
end
end
- end
- end
+ end
- if redundant then
- for i=1,r do
- local r = redundant[i]
- local p, n = getboth(r)
- if r == nuthead then
- nuthead = n
- setprev(n)
- else
- setlink(p,n)
- end
- if b > 0 then
- for i=1,b do
- local bi = basefonts[i]
- local b1 = bi[1]
- local b2 = bi[2]
- if b1 == b2 then
- if b1 == r then
- bi[1] = false
- bi[2] = false
+ if redundant then
+ for i=1,r do
+ local r = redundant[i]
+ local p, n = getboth(r)
+ if r == head then
+ head = n
+ setprev(n)
+ else
+ setlink(p,n)
+ end
+ if b > 0 then
+ for i=1,b do
+ local bi = basefonts[i]
+ local b1 = bi[1]
+ local b2 = bi[2]
+ if b1 == b2 then
+ if b1 == r then
+ bi[1] = false
+ bi[2] = false
+ end
+ elseif b1 == r then
+ bi[1] = n
+ elseif b2 == r then
+ bi[2] = p
end
- elseif b1 == r then
- bi[1] = n
- elseif b2 == r then
- bi[2] = p
end
end
+ flush_node(r)
end
- flush_node(r)
end
- end
- if force_discrun then
-
- -- basefont is not supported in disc only runs ... it would mean a lot of
- -- ranges .. we could try to run basemode as a separate processor run but
- -- not for now (we can consider it when the new node code is tested
- for d in traverse_id(disc_code,nuthead) do
- -- we could use first_glyph, only doing replace is good enough because
- -- pre and post are normally used for hyphens and these come from fonts
- -- that part of the hyphenated word
- local _, _, r = getdisc(d)
- if r then
- local prevfont = nil
- local prevattr = nil
- local none = false
- for n in traverse_char(r) do
- local font = getfont(n)
- local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context
- if font ~= prevfont or attr ~= prevattr then
- prevfont = font
- prevattr = attr
- local fontmode = fontmodes[font]
- if fontmode == "none" then
- setnone(n)
- elseif fontmode == "base" then
- setbase(n)
- else
- setnode(n,font,attr)
+ if force_discrun then
+
+ -- basefont is not supported in disc only runs ... it would mean a lot of
+ -- ranges .. we could try to run basemode as a separate processor run but
+ -- not for now (we can consider it when the new node code is tested
+ for d in nextdisc, head do
+ -- we could use first_glyph, only doing replace is good enough because
+ -- pre and post are normally used for hyphens and these come from fonts
+ -- that part of the hyphenated word
+ local _, _, r = getdisc(d)
+ if r then
+ local prevfont = nil
+ local prevattr = nil
+ local none = false
+ for n, char, font in nextchar, r do
+ local attr = getattr(n) or 0 -- zero attribute is reserved for fonts in context
+ if font ~= prevfont or attr ~= prevattr then
+ prevfont = font
+ prevattr = attr
+ local fontmode = fontmodes[font]
+ if fontmode == "none" then
+ setnone(n)
+ elseif fontmode == "base" then
+ setbase(n)
+ else
+ setnode(n,font,attr)
+ end
+ elseif firstnone then
+ -- lastnone = n
+ lastnone = nil
end
- elseif firstnone then
- -- lastnone = n
- lastnone = nil
+ -- we assume one font for now (and if there are more and we get into issues then
+ -- we can always remove the break)
+ break
end
- -- we assume one font for now (and if there are more and we get into issues then
- -- we can always remove the break)
- break
- end
- if firstnone then
- protectnone()
+ if firstnone then
+ protectnone()
+ end
+ -- elseif expanders then
+ -- local subtype = getsubtype(d)
+ -- if subtype == automaticdisc_code or subtype == explicitdisc_code then
+ -- expanders[subtype](d)
+ -- e = e + 1
+ -- end
end
- -- elseif expanders then
- -- local subtype = getsubtype(d)
- -- if subtype == automatic_code or subtype == explicit_code then
- -- expanders[subtype](d)
- -- e = e + 1
- -- end
end
- end
-
- end
- if trace_fontrun then
- stop_trace(u,usedfonts,a,attrfonts,b,basefonts,r,redundant,e,expanders)
- end
+ end
- -- in context we always have at least 2 processors
- if u == 0 then
- -- skip
- elseif u == 1 then
- local attr = a > 0 and 0 or false -- 0 is the savest way
- for i=1,#lastproc do
- local h, d = lastproc[i](head,lastfont,attr,direction)
- if d then
- if h then
- head = h
- end
- done = true
- end
+ if trace_fontrun then
+ stop_trace(u,usedfonts,a,attrfonts,b,basefonts,r,redundant,e,expanders)
end
- else
- -- local attr = a == 0 and false or 0 -- 0 is the savest way
- local attr = a > 0 and 0 or false -- 0 is the savest way
- for font, processors in next, usedfonts do -- unordered
- for i=1,#processors do
- local h, d = processors[i](head,font,attr,direction,u)
- if d then
- if h then
- head = h
- end
- done = true
- end
+
+ -- in context we always have at least 2 processors
+ if u == 0 then
+ -- skip
+ elseif u == 1 then
+ local attr = a > 0 and 0 or false -- 0 is the savest way
+ for i=1,#lastproc do
+ head = lastproc[i](head,lastfont,attr,direction)
end
- end
- end
- if a == 0 then
- -- skip
- elseif a == 1 then
- local font, dynamics = next(attrfonts)
- for attribute, processors in next, dynamics do -- unordered, attr can switch in between
- for i=1,#processors do
- local h, d = processors[i](head,font,attribute,direction)
- if d then
- if h then
- head = h
- end
- done = true
+ else
+ -- local attr = a == 0 and false or 0 -- 0 is the savest way
+ local attr = a > 0 and 0 or false -- 0 is the savest way
+ for font, processors in next, usedfonts do -- unordered
+ for i=1,#processors do
+ head = processors[i](head,font,attr,direction,u)
end
end
end
- else
- for font, dynamics in next, attrfonts do
+ if a == 0 then
+ -- skip
+ elseif a == 1 then
+ local font, dynamics = next(attrfonts)
for attribute, processors in next, dynamics do -- unordered, attr can switch in between
for i=1,#processors do
- local h, d = processors[i](head,font,attribute,direction,a)
- if d then
- if h then
- head = h
- end
- done = true
- end
+ head = processors[i](head,font,attribute,direction)
end
end
- end
- end
- if b == 0 then
- -- skip
- elseif b == 1 then
- -- only one font
- local range = basefonts[1]
- local start = range[1]
- local stop = range[2]
- if (start or stop) and (start ~= stop) then
- local front = nuthead == start
- if stop then
- start = ligaturing(start,stop)
- start = kerning(start,stop)
- elseif start then -- safeguard
- start = ligaturing(start)
- start = kerning(start)
- end
- if front and nuthead ~= start then
- -- nuthead = start
- head = tonode(start)
+ else
+ for font, dynamics in next, attrfonts do
+ for attribute, processors in next, dynamics do -- unordered, attr can switch in between
+ for i=1,#processors do
+ head = processors[i](head,font,attribute,direction,a)
+ end
+ end
end
end
- else
- -- multiple fonts
- for i=1,b do
- local range = basefonts[i]
+ if b == 0 then
+ -- skip
+ elseif b == 1 then
+ -- only one font
+ local range = basefonts[1]
local start = range[1]
local stop = range[2]
- if start then -- and start ~= stop but that seldom happens
- local front = nuthead == start
- local prev = getprev(start)
- local next = getnext(stop)
+ if (start or stop) and (start ~= stop) then
+ local front = head == start
if stop then
- start, stop = ligaturing(start,stop)
- start, stop = kerning(start,stop)
- else
+ start = ligaturing(start,stop)
+ start = kerning(start,stop)
+ elseif start then -- safeguard
start = ligaturing(start)
start = kerning(start)
end
- -- is done automatically
- if prev then
- setlink(prev,start)
- end
- if next then
- setlink(stop,next)
+ if front and head ~= start then
+ head = start
end
- -- till here
- if front and nuthead ~= start then
- nuthead = start
- head = tonode(start)
+ end
+ else
+ -- multiple fonts
+ for i=1,b do
+ local range = basefonts[i]
+ local start = range[1]
+ local stop = range[2]
+ if start then -- and start ~= stop but that seldom happens
+ local front = head == start
+ local prev = getprev(start)
+ local next = getnext(stop)
+ if stop then
+ start, stop = ligaturing(start,stop)
+ start, stop = kerning(start,stop)
+ else
+ start = ligaturing(start)
+ start = kerning(start)
+ end
+ -- is done automatically
+ if prev then
+ setlink(prev,start)
+ end
+ if next then
+ setlink(stop,next)
+ end
+ -- till here
+ if front and head ~= start then
+ head = start
+ end
end
end
end
+
+ stoptiming(nodes)
+
+ if trace_characters then
+ nodes.report(head)
+ end
+
+ return head
end
- stoptiming(nodes)
- if trace_characters then
- nodes.report(head,done)
- end
- return head, true
+
end
-handlers.protectglyphs = function(n) protect_glyphs (tonut(n)) return n, true end
-handlers.unprotectglyphs = function(n) unprotect_glyphs(tonut(n)) return n, true end
+handlers.protectglyphs = protect_glyphs
+handlers.unprotectglyphs = unprotect_glyphs
diff --git a/tex/context/base/mkiv/node-ini.lua b/tex/context/base/mkiv/node-ini.lua
index 50da140ce..f910c7e01 100644
--- a/tex/context/base/mkiv/node-ini.lua
+++ b/tex/context/base/mkiv/node-ini.lua
@@ -70,6 +70,12 @@ local formatcolumns = utilities.formatters.formatcolumns
local getsubtypes = node.subtypes
local getvalues = node.values
+tex.magicconstants = { -- we use tex.constants for something else
+ running = -1073741824,
+ maxdimen = 1073741823, -- 0x3FFFFFFF or 2^30-1
+ trueinch = 4736286,
+}
+
-- local listcodes = allocate {
-- [0] = "unknown",
-- [1] = "line",
@@ -108,12 +114,11 @@ dircodes = allocate {
}
-- local glyphcodes = allocate {
--- [0] = "character",
--- [1] = "glyph",
--- [2] = "ligature",
--- [3] = "ghost",
--- [4] = "left",
--- [5] = "right",
+-- [ 1] = "character",
+-- [ 2] = "ligature",
+-- [ 4] = "ghost",
+-- [ 8] = "left",
+-- [16] = "right",
-- }
local glyphcodes = mark(getsubtypes("glyph"))
@@ -281,11 +286,12 @@ local function simplified(t)
end
local nodecodes = simplified(node.types())
-local whatcodes = simplified(node.whatsits())
+local whatcodes = simplified(node.whatsits and node.whatsits() or { })
local usercodes = allocate {
[ 97] = "attribute", -- a
[100] = "number", -- d
+ [102] = "float", -- f
[108] = "lua", -- l
[110] = "node", -- n
[115] = "string", -- s
@@ -306,7 +312,7 @@ local noadoptions = allocate {
-- local directionvalues = mark(getvalues("dir"))
-- local gluevalues = mark(getvalues("glue"))
--- local pdfliteralvalues = mark(getvalues("pdf_literal"))
+-- local literalvalues = mark(getvalues("literal"))
local dirvalues = allocate {
[0] = "TLT",
@@ -323,7 +329,7 @@ local gluevalues = allocate {
[4] = "filll",
}
-local pdfliteralvalues = allocate {
+local literalvalues = allocate {
[0] = "origin",
[1] = "page",
[2] = "always",
@@ -356,41 +362,90 @@ usercodes = allocate(swapped(usercodes,usercodes))
noadoptions = allocate(swapped(noadoptions,noadoptions))
dirvalues = allocate(swapped(dirvalues,dirvalues))
gluevalues = allocate(swapped(gluevalues,gluevalues))
-pdfliteralvalues = allocate(swapped(pdfliteralvalues,pdfliteralvalues))
-
-nodes.gluecodes = gluecodes
-nodes.dircodes = dircodes
-nodes.boundarycodes = boundarycodes
-nodes.noadcodes = noadcodes
-nodes.nodecodes = nodecodes
-nodes.whatcodes = whatcodes
-nodes.listcodes = listcodes
-nodes.glyphcodes = glyphcodes
-nodes.kerncodes = kerncodes
-nodes.penaltycodes = penaltycodes
-nodes.mathcodes = mathcodes
-nodes.fillcodes = fillcodes
-nodes.margincodes = margincodes
-nodes.disccodes = disccodes
-nodes.accentcodes = accentcodes
-nodes.radicalcodes = radicalcodes
-nodes.fencecodes = fencecodes
-nodes.rulecodes = rulecodes
-nodes.leadercodes = leadercodes
-nodes.usercodes = usercodes
-nodes.noadoptions = noadoptions
-nodes.dirvalues = dirvalues
-nodes.gluevalues = gluevalues
-nodes.pdfliteralvalues = pdfliteralvalues
-
-nodes.skipcodes = gluecodes -- more friendly
-nodes.directioncodes = dircodes -- more friendly
-nodes.whatsitcodes = whatcodes -- more official
-nodes.marginkerncodes = margincodes
-nodes.discretionarycodes = disccodes
-nodes.directionvalues = dirvalues -- more friendly
-nodes.skipvalues = gluevalues -- more friendly
-nodes.literalvalues = pdfliteralvalues -- more friendly
+literalvalues = allocate(swapped(literalvalues,literalvalues))
+
+if CONTEXTLMTXMODE > 1 then
+ whatcodes.literal = 0x1 whatcodes[0x1] = "literal"
+ whatcodes.latelua = 0x2 whatcodes[0x2] = "latelua"
+ whatcodes.userdefined = 0x3 whatcodes[0x3] = "userdefined"
+ whatcodes.savepos = 0x4 whatcodes[0x4] = "savepos"
+ whatcodes.save = 0x5 whatcodes[0x5] = "save"
+ whatcodes.restore = 0x6 whatcodes[0x6] = "restore"
+ whatcodes.setmatrix = 0x7 whatcodes[0x7] = "setmatrix"
+ whatcodes.open = 0x8 whatcodes[0x8] = "open"
+ whatcodes.close = 0x9 whatcodes[0x9] = "close"
+ whatcodes.write = 0xA whatcodes[0xA] = "write"
+elseif not whatcodes.literal then
+ whatcodes.literal = whatcodes.pdfliteral
+ whatcodes.save = whatcodes.pdfsave
+ whatcodes.restore = whatcodes.pdfrestore
+ whatcodes.setmatrix = whatcodes.pdfsetmatrix
+end
+
+nodes.gluecodes = gluecodes
+nodes.dircodes = dircodes
+nodes.boundarycodes = boundarycodes
+nodes.noadcodes = noadcodes
+nodes.nodecodes = nodecodes
+nodes.whatcodes = whatcodes
+nodes.listcodes = listcodes
+nodes.glyphcodes = glyphcodes
+nodes.kerncodes = kerncodes
+nodes.penaltycodes = penaltycodes
+nodes.mathcodes = mathcodes
+nodes.fillcodes = fillcodes
+nodes.margincodes = margincodes
+nodes.disccodes = disccodes
+nodes.accentcodes = accentcodes
+nodes.radicalcodes = radicalcodes
+nodes.fencecodes = fencecodes
+nodes.rulecodes = rulecodes
+nodes.leadercodes = leadercodes
+nodes.usercodes = usercodes
+nodes.noadoptions = noadoptions
+nodes.dirvalues = dirvalues
+nodes.gluevalues = gluevalues
+nodes.literalvalues = literalvalues
+
+dirvalues.lefttoright = 0
+dirvalues.righttoleft = 1
+
+nodes.subtypes = allocate {
+ [nodecodes.accent] = accentcodes,
+ [nodecodes.boundary] = boundarycodes,
+ [nodecodes.dir] = dircodes,
+ [nodecodes.disc] = disccodes,
+ [nodecodes.fence] = fencecodes,
+ [nodecodes.glue] = gluecodes,
+ [nodecodes.glyph] = glyphcodes,
+ [nodecodes.hlist] = listcodes,
+ [nodecodes.kern] = kerncodes,
+ [nodecodes.marginkern] = margincodes,
+ [nodecodes.math] = mathcodes,
+ [nodecodes.noad] = noadcodes,
+ [nodecodes.penalty] = penaltycodes,
+ [nodecodes.radical] = radicalcodes,
+ [nodecodes.rule] = rulecodes,
+ [nodecodes.vlist] = listcodes,
+ [nodecodes.whatsit] = whatcodes,
+}
+
+table.setmetatableindex(nodes.subtypes,function(t,k)
+ local v = { }
+ t[k] = v
+ return v
+end)
+
+nodes.skipcodes = gluecodes -- more friendly
+nodes.directioncodes = dircodes -- more friendly
+nodes.whatsitcodes = whatcodes -- more official
+nodes.marginkerncodes = margincodes
+nodes.discretionarycodes = disccodes
+nodes.directionvalues = dirvalues -- more friendly
+nodes.skipvalues = gluevalues -- more friendly
+nodes.literalvalues = literalvalues -- more friendly
+
+glyphcodes.glyph = glyphcodes.character
listcodes.row = listcodes.alignment
listcodes.column = listcodes.alignment
@@ -399,7 +454,7 @@ kerncodes.kerning = kerncodes.fontkern
kerncodes.italiccorrection = kerncodes.italiccorrection or 1 -- new
-pdfliteralvalues.direct = pdfliteralvalues.always
+literalvalues.direct = literalvalues.always
nodes.codes = allocate { -- mostly for listing
glue = skipcodes,
@@ -468,4 +523,3 @@ end
if node.fix_node_lists then
node.fix_node_lists(false)
end
-
diff --git a/tex/context/base/mkiv/node-ini.mkiv b/tex/context/base/mkiv/node-ini.mkiv
index 8f1079163..35013c4b8 100644
--- a/tex/context/base/mkiv/node-ini.mkiv
+++ b/tex/context/base/mkiv/node-ini.mkiv
@@ -21,7 +21,7 @@
\registerctxluafile{node-met}{}
\registerctxluafile{node-nut}{}
\registerctxluafile{node-res}{}
-\registerctxluafile{node-ppt}{} % experimental
+%registerctxluafile{node-ppt}{} % experimental, not used so probably useless
\registerctxluafile{node-dir}{}
\registerctxluafile{node-aux}{}
\registerctxluafile{node-tst}{}
@@ -34,9 +34,9 @@
\registerctxluafile{node-ext}{}
\registerctxluafile{node-acc}{} % experimental
%registerctxluafile{node-prp}{} % makes no sense (yet)
-\registerctxluafile{node-ppt}{}
\registerctxluafile{node-scn}{}
\registerctxluafile{node-syn}{}
+\registerctxluafile{node-par}{}
\newcount\c_node_tracers_show_box % box number
diff --git a/tex/context/base/mkiv/node-ltp.lua b/tex/context/base/mkiv/node-ltp.lua
index 865f69c2c..0d501890b 100644
--- a/tex/context/base/mkiv/node-ltp.lua
+++ b/tex/context/base/mkiv/node-ltp.lua
@@ -134,6 +134,53 @@ if not modules then modules = { } end modules ['node-par'] = {
]]--
+--[[--
+
+#define dir_TLT 0
+#define dir_TRT 1
+#define dir_LTL 2
+#define dir_RTT 3
+
+#define dir_TLT_or_TRT(A) (A < 2)
+#define dir_LTL_or_RTT(A) (A > 1)
+
+#define textdir_parallel(A,B) (\
+(dir_TLT_or_TRT(A) and dir_TLT_or_TRT(B)) or \
+(dir_LTL_or_RTT(A) and dir_LTL_or_RTT(B))\
+)
+
+#define pardir_parallel(A,B) (\
+(dir_TLT_or_TRT(A) and dir_TLT_or_TRT(B)) or \
+(dir_LTL_or_RTT(A) and dir_LTL_or_RTT(B))\
+)
+
+#define pardir_opposite(A,B) (\
+(A == dir_LTL and B == dir_RTT) or \
+(A == dir_RTT and B == dir_LTL)\
+)
+
+#define textdir_opposite(A,B) (\
+(A == dir_TLT and B == dir_TRT) or \
+(A == dir_TRT and B == dir_TLT)\
+)
+
+#define glyphdir_opposite(A,B) 0
+
+#define pardir_equal(A,B) (\
+(dir_TLT_or_TRT(A) and dir_TLT_or_TRT(B)) or \
+(A == dir_LTL and B == dir_LTL) or \
+(A == dir_RTT and B == dir_RTT)\
+)
+
+#define textdir_equal(A,B) (\
+(A == dir_TLT and B == dir_TLT) or \
+(A == dir_TRT and B == dir_TRT) or \
+(A == dir_LTL and dir_LTL_or_RTT(B)) or \
+(A == dir_RTT and dir_LTL_or_RTT(B))\
+)
+
+--]]--
+
local tonumber = tonumber
local utfchar = utf.char
local write, write_nl = texio.write, texio.write_nl
@@ -191,7 +238,6 @@ local parameters = fonthashes.parameters
local nuts = nodes.nuts
local tonut = nuts.tonut
-local tonode = nuts.tonode
local getfield = nuts.getfield
local getid = nuts.getid
@@ -200,21 +246,20 @@ local getnext = nuts.getnext
local getprev = nuts.getprev
local getboth = nuts.getboth
local getlist = nuts.getlist
-local getfont = nuts.getfont
-local getchar = nuts.getchar
local getdisc = nuts.getdisc
local getattr = nuts.getattr
local getdisc = nuts.getdisc
local getglue = nuts.getglue
local getwhd = nuts.getwhd
-local getcomponents = nuts.getcomponents
local getkern = nuts.getkern
local getpenalty = nuts.getpenalty
-local getdir = nuts.getdir
+local getdirection = nuts.getdirection
local getshift = nuts.getshift
local getwidth = nuts.getwidth
local getheight = nuts.getheight
local getdepth = nuts.getdepth
+local getdata = nuts.getdata
+local getwhd = nuts.getwhd
local isglyph = nuts.isglyph
@@ -229,11 +274,10 @@ local setsubtype = nuts.setsubtype
local setglue = nuts.setglue
local setwhd = nuts.setwhd
local setkern = nuts.setkern
-local setdir = nuts.setdir
+local setdirection = nuts.setdirection
local setshift = nuts.setshift
local setwidth = nuts.setwidth
------ setheight = nuts.setheight
------ setdepth = nuts.setdepth
+local setexpansion = nuts.setexpansion
local slide_node_list = nuts.slide -- get rid of this, probably ok > 78.2
local find_tail = nuts.tail
@@ -246,13 +290,14 @@ local replace_node = nuts.replace
local insert_node_after = nuts.insert_after
local insert_node_before = nuts.insert_before
local is_zero_glue = nuts.is_zero_glue
+local is_skipable = nuts.protrusion_skippable
local nodepool = nuts.pool
local nodecodes = nodes.nodecodes
local kerncodes = nodes.kerncodes
local glyphcodes = nodes.glyphcodes
-local gluecodes = nodes.gluecodes
+local leadercodes = nodes.leadercodes
local margincodes = nodes.margincodes
local disccodes = nodes.disccodes
local mathcodes = nodes.mathcodes
@@ -276,9 +321,9 @@ local marginkern_code = nodecodes.marginkern
local dir_code = nodecodes.dir
local boundary_code = nodecodes.boundary
-local protrusion_code = boundarycodes.protrusion
+local protrusionboundary_code = boundarycodes.protrusion
-local leaders_code = gluecodes.leaders
+local leaders_code = leadercodes.leaders
local localpar_code = nodecodes.localpar
@@ -287,17 +332,17 @@ local italickern_code = kerncodes.italiccorrection
local fontkern_code = kerncodes.fontkern
local accentkern_code = kerncodes.accentkern
-local ligature_code = glyphcodes.ligature
+local ligatureglyph_code = glyphcodes.ligature
-local stretch_orders = nodes.fillcodes
+local fillcodes = nodes.fillcodes
local leftmargin_code = margincodes.left
----- rightmargin_code = margincodes.right
-local automatic_disc_code = disccodes.automatic
-local regular_disc_code = disccodes.regular
-local first_disc_code = disccodes.first
-local second_disc_code = disccodes.second
+local automaticdisc_code = disccodes.automatic
+local regulardisc_code = disccodes.regular
+local firstdisc_code = disccodes.first
+local seconddisc_code = disccodes.second
local endmath_code = mathcodes.endmath
@@ -323,7 +368,7 @@ local fit_decent_class = 2 -- fitness for all other lines
local fit_tight_class = 3 -- fitness for lines shrinking 0.5 to 1.0 of their shrinkability
local new_penalty = nodepool.penalty
-local new_dir = nodepool.textdir
+local new_direction = nodepool.direction
local new_leftmarginkern = nodepool.leftmarginkern
local new_rightmarginkern = nodepool.rightmarginkern
local new_leftskip = nodepool.leftskip
@@ -334,17 +379,6 @@ local new_temp = nodepool.temp
local new_rule = nodepool.rule
local new_hlist = nodepool.hlist
-local is_rotated = nodes.is_rotated
-local is_parallel = nodes.textdir_is_parallel
-local is_opposite = nodes.textdir_is_opposite
-local textdir_is_equal = nodes.textdir_is_equal
-local pardir_is_equal = nodes.pardir_is_equal
-local glyphdir_is_equal = nodes.glyphdir_is_equal
-
-local dir_pops = nodes.dir_is_pop
-local dir_negations = nodes.dir_negation
-local is_skipable = nuts.protrusion_skippable
-
-- helpers --
-- It makes more sense to move the somewhat messy dir state tracking
@@ -359,22 +393,24 @@ end
-- in the parbuilder.
local function checked_line_dir(stack,current)
- if not dir_pops[current] then
+ local direction, pop = getdirection(current)
+ if not pop then
local n = stack.n + 1
stack.n = n
stack[n] = current
- return getdir(current)
+ return direction
elseif n > 0 then
local n = stack.n
local dirnode = stack[n]
dirstack.n = n - 1
- return getdir(dirnode)
+ direction = getdirection(dirnode) -- we could save it
+ return direction
else
report_parbuilders("warning: missing pop node (%a)",1) -- in line ...
end
end
--- The next function checks a dir nodes in a list and appends the negations
+-- The next function checks dir nodes in a list and appends the negations
-- that are currently needed (some day LuaTeX will be more tolerant). We use
-- the negations for the next line.
@@ -382,10 +418,12 @@ local function inject_dirs_at_end_of_line(stack,current,start,stop)
local e = start
local n = stack.n
local h = nil
+ -- todo: traverse
while start and start ~= stop do
local id = getid(start)
if id == dir_code then
- if not dir_pops[getdir(start)] then -- weird, what is this #
+ local direction, pop = getdirection(start)
+ if not pop then
n = n + 1
stack[n] = start
elseif n > 0 then
@@ -397,7 +435,7 @@ local function inject_dirs_at_end_of_line(stack,current,start,stop)
start = getnext(start)
end
for i=n,1,-1 do
- h, current = insert_node_after(current,current,new_dir(dir_negations[getdir(stack[i])]))
+ h, current = insert_node_after(current,current,new_direction(getdirection(stack[i]),true))
end
stack.n = n
return current
@@ -406,7 +444,7 @@ end
local function inject_dirs_at_begin_of_line(stack,current)
local h = nil
for i=stack.n,1,-1 do
- h, current = insert_node_after(current,current,new_dir(stack[i]))
+ h, current = insert_node_after(current,current,new_direction(stack[i]))
end
stack.n = 0
return current
@@ -507,9 +545,9 @@ end)
local function kern_stretch_shrink(p,d)
local left = getprev(p)
if left then
- local char = isglyph(left)
+ local char, font = isglyph(left)
if char then
- local data = expansions[getfont(left)][char]
+ local data = expansions[font][char]
if data then
local stretch = data.stretch
local shrink = data.shrink
@@ -630,8 +668,8 @@ local function find(head) -- do we really want to recurse into an hlist?
head = getnext(head)
end
elseif id == boundary_code then
- if getsubtype(head) == protrusion_code then
- local v = getfield(head,"value")
+ if getsubtype(head) == protrusionboundary_code then
+ local v = getdata(head)
if v == 1 or v == 3 then
head = getnext(head)
if head then
@@ -654,19 +692,19 @@ end
local function find_protchar_left(l) -- weird function
local ln = getnext(l)
- if ln and getid(ln) == hlist_code and not getlist(ln) and getfield(ln,"width") == 0 and getfield(ln,"height") == 0 and getfield(ln,"depth") == 0 then
- l = getnext(l)
- else -- if d then -- was always true
- local id = getid(l)
- while ln and not (id == glyph_code or id < math_code) do -- is there always a glyph?
- l = ln
- ln = getnext(l)
- id = getid(ln)
- end
+ if ln and getid(ln) == hlist_code and not getlist(ln) then
+ local w, h, d = getwhd(ln)
+ if w == 0 and h == 0 and d == 0 then
+ l = getnext(l)
+ return find(l) or l
+ end
+ end -- if d then -- was always true
+ local id = getid(l)
+ while ln and not (id == glyph_code or id < math_code) do -- is there always a glyph?
+ l = ln
+ ln = getnext(l)
+ id = getid(ln)
end
- -- if getid(l) == glyph_code then
- -- return l
- -- end
return find(l) or l
end
@@ -684,8 +722,8 @@ local function find(head,tail)
tail = getprev(tail)
end
elseif id == boundary_code then
- if getsubtype(head) == protrusion_code then
- local v = getfield(tail,"value")
+ if getsubtype(head) == protrusionboundary_code then
+ local v = getdata(tail)
if v == 2 or v == 3 then
tail = getprev(tail)
if tail then
@@ -711,8 +749,8 @@ local function find_protchar_right(l,r)
end
local function left_pw(p)
- local font = getfont(p)
- local prot = chardata[font][getchar(p)].left_protruding
+ local char, font = isglyph(p)
+ local prot = chardata[font][char].left_protruding
if not prot or prot == 0 then
return 0
end
@@ -720,8 +758,8 @@ local function left_pw(p)
end
local function right_pw(p)
- local font = getfont(p)
- local prot = chardata[font][getchar(p)].right_protruding
+ local char, font = isglyph(p)
+ local prot = chardata[font][char].right_protruding
if not prot or prot == 0 then
return 0
end
@@ -748,13 +786,13 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw
local char, id = isglyph(s)
if char then
local wd, ht, dp = getwhd(s)
- if is_rotated[line_break_dir] then -- can be shared
+ if is_rotated(line_break_dir) then
size = size + ht + dp
else
size = size + wd
end
if checked_expansion then
- local data = checked_expansion[getfont(s)]
+ local data = checked_expansion[id] -- id == font
if data then
data = data[char]
if data then
@@ -765,7 +803,7 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw
end
elseif id == hlist_code or id == vlist_code then
local wd, ht, dp = getwhd(s)
- if is_parallel[getdir(s)][line_break_dir] then
+ if textdir_parallel(getdirection(s),line_break_dir) then
size = size + wd
else
size = size + ht + dp
@@ -796,1709 +834,1712 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw
return size, adjust_stretch, adjust_shrink
end
-local function compute_break_width(par,break_type,p) -- split in two
- local break_width = par.break_width
- if break_type > unhyphenated_code then
- local disc_width = par.disc_width
- local checked_expansion = par.checked_expansion
- local line_break_dir = par.line_break_dir
- local break_size = break_width.size + disc_width.size
- local break_adjust_stretch = break_width.adjust_stretch + disc_width.adjust_stretch
- local break_adjust_shrink = break_width.adjust_shrink + disc_width.adjust_shrink
- local pre, post, replace = getdisc(p)
- if replace then
- local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace)
- break_size = break_size - size
- break_adjust_stretch = break_adjust_stretch - adjust_stretch
- break_adjust_shrink = break_adjust_shrink - adjust_shrink
- end
- if post then
- local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,post)
- break_size = break_size + size
- break_adjust_stretch = break_adjust_stretch + adjust_stretch
- break_adjust_shrink = break_adjust_shrink + adjust_shrink
- end
- break_width.size = break_size
- break_width.adjust_stretch = break_adjust_stretch
- break_width.adjust_shrink = break_adjust_shrink
- if not post then
- p = getnext(p)
- else
- return
- end
- end
- while p do -- skip spacing etc
- local id = getid(p)
- if id == glyph_code then
- return -- happens often
- elseif id == glue_code then
- local wd, stretch, shrink, stretch_order = getglue(p)
- local order = stretch_orders[stretch_order]
- break_width.size = break_width.size - wd
- break_width[order] = break_width[order] - stretch
- break_width.shrink = break_width.shrink - shrink
- elseif id == penalty_code then
- -- do nothing
- elseif id == kern_code then
- local s = getsubtype(p)
- if s == userkern_code or s == italickern_code then
- break_width.size = break_width.size - getkern(p)
+-- We can actually make par local to this module as we never break inside a break call and that way the
+-- array is reused. At some point the information will be part of the paragraph spec as passed.
+
+local hztolerance = 2500
+local hzwarned = false
+
+do
+
+ local function compute_break_width(par,break_type,p) -- split in two
+ local break_width = par.break_width
+ if break_type > unhyphenated_code then
+ local disc_width = par.disc_width
+ local checked_expansion = par.checked_expansion
+ local line_break_dir = par.line_break_dir
+ local break_size = break_width.size + disc_width.size
+ local break_adjust_stretch = break_width.adjust_stretch + disc_width.adjust_stretch
+ local break_adjust_shrink = break_width.adjust_shrink + disc_width.adjust_shrink
+ local pre, post, replace = getdisc(p)
+ if replace then
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace)
+ break_size = break_size - size
+ break_adjust_stretch = break_adjust_stretch - adjust_stretch
+ break_adjust_shrink = break_adjust_shrink - adjust_shrink
+ end
+ if post then
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,post)
+ break_size = break_size + size
+ break_adjust_stretch = break_adjust_stretch + adjust_stretch
+ break_adjust_shrink = break_adjust_shrink + adjust_shrink
+ end
+ break_width.size = break_size
+ break_width.adjust_stretch = break_adjust_stretch
+ break_width.adjust_shrink = break_adjust_shrink
+ if not post then
+ p = getnext(p)
else
return
end
- elseif id == math_code then
- break_width.size = break_width.size - getkern(p) -- surround
- -- new in luatex
- local wd, stretch, shrink, stretch_order = getglue(p)
- local order = stretch_orders[stretch_order]
- break_width.size = break_width.size - wd
- break_width[order] = break_width[order] - stretch
- break_width.shrink = break_width.shrink - shrink
- else
- return
end
- p = getnext(p)
- end
-end
-
-local function append_to_vlist(par, b)
- local prev_depth = par.prev_depth
- local head_field = par.head_field
- local tail_field = head_field and slide_node_list(head_field) -- todo: find_tail
- local is_hlist = getid(b) == hlist_code
- -- if prev_depth > par.ignored_dimen then
- if prev_depth > ignore_depth then
- if is_hlist then
- local width, stretch, shrink, stretch_order, shrink_order = getglue(par.baseline_skip)
- local delta = width - prev_depth - getheight(b) -- deficiency of space between baselines
- local skip = nil
- if delta < par.line_skip_limit then
- width, stretch, shrink, stretch_order, shrink_order = getglue(par.lineskip)
- skip = new_lineskip(width, stretch, shrink, stretch_order, shrink_order)
- else
- skip = new_baselineskip(delta, stretch, shrink, stretch_order, shrink_order)
- end
- if head_field then
- setlink(tail_field,skip)
+ while p do -- skip spacing etc
+ local id = getid(p)
+ if id == glyph_code then
+ return -- happens often
+ elseif id == glue_code then
+ local wd, stretch, shrink, stretch_order = getglue(p)
+ local order = fillcodes[stretch_order]
+ break_width.size = break_width.size - wd
+ break_width[order] = break_width[order] - stretch
+ break_width.shrink = break_width.shrink - shrink
+ elseif id == penalty_code then
+ -- do nothing
+ elseif id == kern_code then
+ local s = getsubtype(p)
+ if s == userkern_code or s == italickern_code then
+ break_width.size = break_width.size - getkern(p)
+ else
+ return
+ end
+ elseif id == math_code then
+ break_width.size = break_width.size - getkern(p) -- surround
+ -- new in luatex
+ local wd, stretch, shrink, stretch_order = getglue(p)
+ local order = fillcodes[stretch_order]
+ break_width.size = break_width.size - wd
+ break_width[order] = break_width[order] - stretch
+ break_width.shrink = break_width.shrink - shrink
else
- par.head_field = skip
- head_field = skip
+ return
end
- tail_field = skip
+ p = getnext(p)
end
end
- if head_field then
- setlink(tail_field,b)
- else
- par.head_field = b
- end
- if is_hlist then
- local pd = getdepth(b)
- par.prev_depth = pd
- texnest[texnest.ptr].prevdepth = pd
- end
-end
-local function append_list(par, b)
- local head_field = par.head_field
- if head_field then
- local n = slide_node_list(head_field) -- todo: find_tail
- setlink(n,b)
- else
- par.head_field = b
+ local function append_to_vlist(par, b)
+ local prev_depth = par.prev_depth
+ local head_field = par.head_field
+ local tail_field = head_field and slide_node_list(head_field) -- todo: find_tail
+ local is_hlist = getid(b) == hlist_code
+ -- if prev_depth > par.ignored_dimen then
+ if prev_depth > ignore_depth then
+ if is_hlist then
+ local width, stretch, shrink, stretch_order, shrink_order = getglue(par.baseline_skip)
+ local delta = width - prev_depth - getheight(b) -- deficiency of space between baselines
+ local skip = nil
+ if delta < par.line_skip_limit then
+ width, stretch, shrink, stretch_order, shrink_order = getglue(par.lineskip)
+ skip = new_lineskip(width, stretch, shrink, stretch_order, shrink_order)
+ else
+ skip = new_baselineskip(delta, stretch, shrink, stretch_order, shrink_order)
+ end
+ if head_field then
+ setlink(tail_field,skip)
+ else
+ par.head_field = skip
+ head_field = skip
+ end
+ tail_field = skip
+ end
+ end
+ if head_field then
+ setlink(tail_field,b)
+ else
+ par.head_field = b
+ end
+ if is_hlist then
+ local pd = getdepth(b)
+ par.prev_depth = pd
+ texnest[texnest.ptr].prevdepth = pd
+ end
end
-end
-
--- We can actually make par local to this module as we never break inside a break call and that way the
--- array is reused. At some point the information will be part of the paragraph spec as passed.
-
-local hztolerance = 2500
-local hzwarned = false
-
-local function used_skip(s)
- return s and not is_zero_glue(s) and s
-end
-local function initialize_line_break(head,display)
-
- local hang_indent = tex.hangindent or 0
- local hsize = tex.hsize or 0
- local hang_after = tex.hangafter or 0
- local par_shape_ptr = tex.parshape
- local left_skip = tonut(tex.leftskip) -- nodes
- local right_skip = tonut(tex.rightskip) -- nodes
- local pretolerance = tex.pretolerance
- local tolerance = tex.tolerance
- local adjust_spacing = tex.adjustspacing
- local protrude_chars = tex.protrudechars
- local last_line_fit = tex.lastlinefit
-
- local newhead = new_temp()
- setnext(newhead,head)
-
- local adjust_spacing_status = adjust_spacing > 1 and -1 or 0
-
- -- metatables
-
- local par = {
- head = newhead,
- head_field = nil,
- display = display,
- font_in_short_display = 0,
- no_shrink_error_yet = true, -- have we complained about infinite shrinkage?
- second_pass = false, -- is this our second attempt to break this paragraph?
- final_pass = false, -- is this our final attempt to break this paragraph?
- threshold = 0, -- maximum badness on feasible lines
-
- passive = nil, -- most recent node on passive list
- printed_node = head, -- most recent node that has been printed
- pass_number = 0, -- the number of passive nodes allocated on this pass
- auto_breaking = 0, -- make auto_breaking accessible out of line_break
-
- active_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 },
- break_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 },
- disc_width = { size = 0, adjust_stretch = 0, adjust_shrink = 0 },
- fill_width = { stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 },
- background = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 },
-
- hang_indent = hang_indent,
- hsize = hsize,
- hang_after = hang_after,
- par_shape_ptr = par_shape_ptr,
- left_skip = left_skip,
- right_skip = right_skip,
- pretolerance = pretolerance,
- tolerance = tolerance,
-
- protrude_chars = protrude_chars,
- adjust_spacing = adjust_spacing,
- max_stretch_ratio = adjust_spacing_status,
- max_shrink_ratio = adjust_spacing_status,
- cur_font_step = adjust_spacing_status,
- checked_expansion = false,
- tracing_paragraphs = tex.tracingparagraphs > 0,
-
- emergency_stretch = tex.emergencystretch or 0,
- looseness = tex.looseness or 0,
- line_penalty = tex.linepenalty or 0,
- hyphen_penalty = tex.hyphenpenalty or 0,
- broken_penalty = tex.brokenpenalty or 0,
- inter_line_penalty = tex.interlinepenalty or 0,
- club_penalty = tex.clubpenalty or 0,
- widow_penalty = tex.widowpenalty or 0,
- display_widow_penalty = tex.displaywidowpenalty or 0,
- ex_hyphen_penalty = tex.exhyphenpenalty or 0,
-
- adj_demerits = tex.adjdemerits or 0,
- double_hyphen_demerits = tex.doublehyphendemerits or 0,
- final_hyphen_demerits = tex.finalhyphendemerits or 0,
-
- first_line = 0, -- tex.nest[tex.nest.ptr].modeline, -- 0, -- cur_list.pg_field
-
- -- each_line_height = tex.pdfeachlineheight or 0, -- this will go away
- -- each_line_depth = tex.pdfeachlinedepth or 0, -- this will go away
- -- first_line_height = tex.pdffirstlineheight or 0, -- this will go away
- -- last_line_depth = tex.pdflastlinedepth or 0, -- this will go away
-
- -- ignored_dimen = tex.pdfignoreddimen or 0,
-
- baseline_skip = tonut(tex.baselineskip),
- lineskip = tonut(tex.lineskip),
- line_skip_limit = tex.lineskiplimit,
-
- prev_depth = texnest[texnest.ptr].prevdepth,
-
- final_par_glue = slide_node_list(head), -- todo: we know tail already, slow
-
- par_break_dir = tex.pardir,
- line_break_dir = tex.pardir,
-
- internal_pen_inter = 0, -- running localinterlinepenalty
- internal_pen_broken = 0, -- running localbrokenpenalty
- internal_left_box = nil, -- running localleftbox
- internal_left_box_width = 0, -- running localleftbox width
- init_internal_left_box = nil, -- running localleftbox
- init_internal_left_box_width = 0, -- running localleftbox width
- internal_right_box = nil, -- running localrightbox
- internal_right_box_width = 0, -- running localrightbox width
-
- best_place = { }, -- how to achieve minimal_demerits
- best_pl_line = { }, -- corresponding line number
- easy_line = 0, -- line numbers easy_line are equivalent in break nodes
- last_special_line = 0, -- line numbers last_special_line all have the same width
- first_width = 0, -- the width of all lines last_special_line, if no parshape has been specified
- second_width = 0, -- the width of all lines last_special_line
- first_indent = 0, -- left margin to go with first_width
- second_indent = 0, -- left margin to go with second_width
-
- best_bet = nil, -- use this passive node and its predecessors
- fewest_demerits = 0, -- the demerits associated with best_bet
- best_line = 0, -- line number following the last line of the new paragraph
- line_diff = 0, -- the difference between the current line number and the optimum best_line
-
- -- not yet used
-
- best_pl_short = { }, -- shortfall corresponding to minimal_demerits
- best_pl_glue = { }, -- corresponding glue stretch or shrink
- do_last_line_fit = false,
- last_line_fit = last_line_fit,
-
- minimum_demerits = awful_badness,
-
- minimal_demerits = {
-
- [fit_very_loose_class] = awful_badness,
- [fit_loose_class] = awful_badness,
- [fit_decent_class] = awful_badness,
- [fit_tight_class] = awful_badness,
-
- },
-
- prev_char_p = nil,
-
- statistics = {
-
- noflines = 0,
- nofprotrudedlines = 0,
- nofadjustedlines = 0,
-
- },
-
- -- -- just a thought ... parshape functions ... it would be nice to
- -- -- also store the height so far (probably not too hard) although
- -- -- in most cases we work on grids in such cases
- --
- -- adapt_width = function(par,line)
- -- -- carry attribute, so that we can accumulate
- -- local left = 655360 * (line - 1)
- -- local right = 655360 * (line - 1)
- -- return left, right
- -- end
+ local function append_list(par, b)
+ local head_field = par.head_field
+ if head_field then
+ local n = slide_node_list(head_field) -- todo: find_tail
+ setlink(n,b)
+ else
+ par.head_field = b
+ end
+ end
+
+ local function used_skip(s)
+ return s and not is_zero_glue(s) and s
+ end
+
+ local function initialize_line_break(head,display)
+
+ local hang_indent = tex.hangindent or 0
+ local hsize = tex.hsize or 0
+ local hang_after = tex.hangafter or 0
+ local par_shape_ptr = tex.parshape
+ local left_skip = tonut(tex.leftskip) -- nodes
+ local right_skip = tonut(tex.rightskip) -- nodes
+ local pretolerance = tex.pretolerance
+ local tolerance = tex.tolerance
+ local adjust_spacing = tex.adjustspacing
+ local protrude_chars = tex.protrudechars
+ local last_line_fit = tex.lastlinefit
+ local par_dir = tex.pardirection
+
+ local newhead = new_temp()
+ setnext(newhead,head)
+
+ local adjust_spacing_status = adjust_spacing > 1 and -1 or 0
+
+ -- metatables
+
+ local par = {
+ head = newhead,
+ head_field = nil,
+ display = display,
+ font_in_short_display = 0,
+ no_shrink_error_yet = true, -- have we complained about infinite shrinkage?
+ second_pass = false, -- is this our second attempt to break this paragraph?
+ final_pass = false, -- is this our final attempt to break this paragraph?
+ threshold = 0, -- maximum badness on feasible lines
+
+ passive = nil, -- most recent node on passive list
+ printed_node = head, -- most recent node that has been printed
+ pass_number = 0, -- the number of passive nodes allocated on this pass
+ auto_breaking = 0, -- make auto_breaking accessible out of line_break
+
+ active_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 },
+ break_width = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0, adjust_stretch = 0, adjust_shrink = 0 },
+ disc_width = { size = 0, adjust_stretch = 0, adjust_shrink = 0 },
+ fill_width = { stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 },
+ background = { size = 0, stretch = 0, fi = 0, fil = 0, fill = 0, filll = 0, shrink = 0 },
+
+ hang_indent = hang_indent,
+ hsize = hsize,
+ hang_after = hang_after,
+ par_shape_ptr = par_shape_ptr,
+ left_skip = left_skip,
+ right_skip = right_skip,
+ pretolerance = pretolerance,
+ tolerance = tolerance,
+
+ protrude_chars = protrude_chars,
+ adjust_spacing = adjust_spacing,
+ max_stretch_ratio = adjust_spacing_status,
+ max_shrink_ratio = adjust_spacing_status,
+ cur_font_step = adjust_spacing_status,
+ checked_expansion = false,
+ tracing_paragraphs = tex.tracingparagraphs > 0,
+
+ emergency_stretch = tex.emergencystretch or 0,
+ looseness = tex.looseness or 0,
+ line_penalty = tex.linepenalty or 0,
+ hyphen_penalty = tex.hyphenpenalty or 0,
+ broken_penalty = tex.brokenpenalty or 0,
+ inter_line_penalty = tex.interlinepenalty or 0,
+ club_penalty = tex.clubpenalty or 0,
+ widow_penalty = tex.widowpenalty or 0,
+ display_widow_penalty = tex.displaywidowpenalty or 0,
+ ex_hyphen_penalty = tex.exhyphenpenalty or 0,
+
+ adj_demerits = tex.adjdemerits or 0,
+ double_hyphen_demerits = tex.doublehyphendemerits or 0,
+ final_hyphen_demerits = tex.finalhyphendemerits or 0,
+
+ first_line = 0, -- texnest[texnest.ptr].modeline, -- 0, -- cur_list.pg_field
+
+ -- each_line_height = tex.pdfeachlineheight or 0, -- this will go away
+ -- each_line_depth = tex.pdfeachlinedepth or 0, -- this will go away
+ -- first_line_height = tex.pdffirstlineheight or 0, -- this will go away
+ -- last_line_depth = tex.pdflastlinedepth or 0, -- this will go away
+
+ -- ignored_dimen = tex.pdfignoreddimen or 0,
+
+ baseline_skip = tonut(tex.baselineskip),
+ lineskip = tonut(tex.lineskip),
+ line_skip_limit = tex.lineskiplimit,
+
+ prev_depth = texnest[texnest.ptr].prevdepth,
+
+ final_par_glue = slide_node_list(head), -- todo: we know tail already, slow
+
+ par_break_dir = par_dir,
+ line_break_dir = par_dir,
+
+ internal_pen_inter = 0, -- running localinterlinepenalty
+ internal_pen_broken = 0, -- running localbrokenpenalty
+ internal_left_box = nil, -- running localleftbox
+ internal_left_box_width = 0, -- running localleftbox width
+ init_internal_left_box = nil, -- running localleftbox
+ init_internal_left_box_width = 0, -- running localleftbox width
+ internal_right_box = nil, -- running localrightbox
+ internal_right_box_width = 0, -- running localrightbox width
+
+ best_place = { }, -- how to achieve minimal_demerits
+ best_pl_line = { }, -- corresponding line number
+ easy_line = 0, -- line numbers easy_line are equivalent in break nodes
+ last_special_line = 0, -- line numbers last_special_line all have the same width
+ first_width = 0, -- the width of all lines last_special_line, if no parshape has been specified
+ second_width = 0, -- the width of all lines last_special_line
+ first_indent = 0, -- left margin to go with first_width
+ second_indent = 0, -- left margin to go with second_width
+
+ best_bet = nil, -- use this passive node and its predecessors
+ fewest_demerits = 0, -- the demerits associated with best_bet
+ best_line = 0, -- line number following the last line of the new paragraph
+ line_diff = 0, -- the difference between the current line number and the optimum best_line
+
+ -- not yet used
+
+ best_pl_short = { }, -- shortfall corresponding to minimal_demerits
+ best_pl_glue = { }, -- corresponding glue stretch or shrink
+ do_last_line_fit = false,
+ last_line_fit = last_line_fit,
+
+ minimum_demerits = awful_badness,
+
+ minimal_demerits = {
+
+ [fit_very_loose_class] = awful_badness,
+ [fit_loose_class] = awful_badness,
+ [fit_decent_class] = awful_badness,
+ [fit_tight_class] = awful_badness,
+
+ },
+
+ prev_char_p = nil,
+
+ statistics = {
+
+ noflines = 0,
+ nofprotrudedlines = 0,
+ nofadjustedlines = 0,
+
+ },
+
+ -- -- just a thought ... parshape functions ... it would be nice to
+ -- -- also store the height so far (probably not too hard) although
+ -- -- in most cases we work on grids in such cases
+ --
+ -- adapt_width = function(par,line)
+ -- -- carry attribute, so that we can accumulate
+ -- local left = 655360 * (line - 1)
+ -- local right = 655360 * (line - 1)
+ -- return left, right
+ -- end
- }
+ }
- -- optimizers
+ -- optimizers
- par.used_left_skip = used_skip(par.left_skip)
- par.used_right_skip = used_skip(par.right_skip)
+ par.used_left_skip = used_skip(par.left_skip)
+ par.used_right_skip = used_skip(par.right_skip)
- -- so far
+ -- so far
- if adjust_spacing > 1 then
- local checked_expansion = { par = par }
- setmetatableindex(checked_expansion,check_expand_pars)
- par.checked_expansion = checked_expansion
+ if adjust_spacing > 1 then
+ local checked_expansion = { par = par }
+ setmetatableindex(checked_expansion,check_expand_pars)
+ par.checked_expansion = checked_expansion
- if par.tolerance < hztolerance then
- if not hzwarned then
- report_parbuilders("setting tolerance to %a for hz",hztolerance)
- hzwarned = true
+ if par.tolerance < hztolerance then
+ if not hzwarned then
+ report_parbuilders("setting tolerance to %a for hz",hztolerance)
+ hzwarned = true
+ end
+ par.tolerance = hztolerance
end
- par.tolerance = hztolerance
- end
- expand_kerns = expand_kerns_mode or (adjust_spacing == 2)
+ expand_kerns = expand_kerns_mode or (adjust_spacing == 2)
- end
+ end
- -- we need par for the error message
+ -- we need par for the error message
- local background = par.background
+ local background = par.background
- local l = check_shrinkage(par,left_skip)
- local r = check_shrinkage(par,right_skip)
+ local l = check_shrinkage(par,left_skip)
+ local r = check_shrinkage(par,right_skip)
- local lwidth, lstretch, lshrink, lstretch_order, lshrink_order = getglue(l)
- local rwidth, rstretch, rshrink, rstretch_order, rshrink_order = getglue(r)
+ local lwidth, lstretch, lshrink, lstretch_order, lshrink_order = getglue(l)
+ local rwidth, rstretch, rshrink, rstretch_order, rshrink_order = getglue(r)
- local l_order = stretch_orders[lstretch_order]
- local r_order = stretch_orders[rstretch_order]
+ local l_order = fillcodes[lstretch_order]
+ local r_order = fillcodes[rstretch_order]
- background.size = lwidth + rwidth
- background.shrink = lshrink + rshrink
- background[l_order] = lstretch
- background[r_order] = rstretch + background[r_order]
+ background.size = lwidth + rwidth
+ background.shrink = lshrink + rshrink
+ background[l_order] = lstretch
+ background[r_order] = rstretch + background[r_order]
- -- this will move up so that we can assign the whole par table
+ -- this will move up so that we can assign the whole par table
- if not par_shape_ptr then
- if hang_indent == 0 then
- par.second_width = hsize
- par.second_indent = 0
- else
- local abs_hang_after = hang_after >0 and hang_after or -hang_after
- local abs_hang_indent = hang_indent>0 and hang_indent or -hang_indent
- par.last_special_line = abs_hang_after
- if hang_after < 0 then
- par.first_width = hsize - abs_hang_indent
- if hang_indent >= 0 then
- par.first_indent = hang_indent
- else
- par.first_indent = 0
- end
+ if not par_shape_ptr then
+ if hang_indent == 0 then
par.second_width = hsize
par.second_indent = 0
else
- par.first_width = hsize
- par.first_indent = 0
- par.second_width = hsize - abs_hang_indent
- if hang_indent >= 0 then
- par.second_indent = hang_indent
- else
+ local abs_hang_after = hang_after >0 and hang_after or -hang_after
+ local abs_hang_indent = hang_indent>0 and hang_indent or -hang_indent
+ par.last_special_line = abs_hang_after
+ if hang_after < 0 then
+ par.first_width = hsize - abs_hang_indent
+ if hang_indent >= 0 then
+ par.first_indent = hang_indent
+ else
+ par.first_indent = 0
+ end
+ par.second_width = hsize
par.second_indent = 0
+ else
+ par.first_width = hsize
+ par.first_indent = 0
+ par.second_width = hsize - abs_hang_indent
+ if hang_indent >= 0 then
+ par.second_indent = hang_indent
+ else
+ par.second_indent = 0
+ end
end
end
+ else
+ local last_special_line = #par_shape_ptr
+ par.last_special_line = last_special_line
+ local parshape = par_shape_ptr[last_special_line]
+ par.second_width = parshape[2]
+ par.second_indent = parshape[1]
end
- else
- local last_special_line = #par_shape_ptr
- par.last_special_line = last_special_line
- local parshape = par_shape_ptr[last_special_line]
- par.second_width = parshape[2]
- par.second_indent = parshape[1]
- end
- if par.looseness == 0 then
- par.easy_line = par.last_special_line
- else
- par.easy_line = max_halfword
- end
+ if par.looseness == 0 then
+ par.easy_line = par.last_special_line
+ else
+ par.easy_line = max_halfword
+ end
- if pretolerance >= 0 then
- par.threshold = pretolerance
- par.second_pass = false
- par.final_pass = false
- else
- par.threshold = tolerance
- par.second_pass = true
- par.final_pass = par.emergency_stretch <= 0
- if trace_basic then
- if par.final_pass then
- report_parbuilders("enabling second and final pass")
- else
- report_parbuilders("enabling second pass")
+ if pretolerance >= 0 then
+ par.threshold = pretolerance
+ par.second_pass = false
+ par.final_pass = false
+ else
+ par.threshold = tolerance
+ par.second_pass = true
+ par.final_pass = par.emergency_stretch <= 0
+ if trace_basic then
+ if par.final_pass then
+ report_parbuilders("enabling second and final pass")
+ else
+ report_parbuilders("enabling second pass")
+ end
end
end
- end
- if last_line_fit > 0 then
- local final_par_glue = par.final_par_glue
- local stretch = getfield(final_par_glue,"stretch")
- local stretch_order = getfield(final_par_glue,"stretch_order")
- if stretch > 0 and stretch_order > 0 and background.fi == 0 and background.fil == 0 and background.fill == 0 and background.filll == 0 then
- par.do_last_line_fit = true
- local si = stretch_orders[stretch_order]
- if trace_lastlinefit or trace_basic then
- report_parbuilders("enabling last line fit, stretch order %a set to %a, linefit is %a",si,stretch,last_line_fit)
+ if last_line_fit > 0 then
+ local final_par_glue = par.final_par_glue
+ local stretch = getfield(final_par_glue,"stretch")
+ local stretch_order = getfield(final_par_glue,"stretch_order")
+ if stretch > 0 and stretch_order > 0 and background.fi == 0 and background.fil == 0 and background.fill == 0 and background.filll == 0 then
+ par.do_last_line_fit = true
+ local si = fillcodes[stretch_order]
+ if trace_lastlinefit or trace_basic then
+ report_parbuilders("enabling last line fit, stretch order %a set to %a, linefit is %a",si,stretch,last_line_fit)
+ end
+ par.fill_width[si] = stretch
end
- par.fill_width[si] = stretch
end
- end
- return par
-end
+ return par
+ end
--- there are still all kind of artefacts in here (a side effect I guess of pdftex,
--- etex, omega and other extensions that got obscured by patching)
+ -- there are still all kind of artefacts in here (a side effect I guess of pdftex,
+ -- etex, omega and other extensions that got obscured by patching)
-local function post_line_break(par)
+ local function post_line_break(par)
- local prevgraf = texnest[texnest.ptr].prevgraf
- local current_line = prevgraf + 1 -- the current line number being justified
+ local prevgraf = texnest[texnest.ptr].prevgraf
+ local current_line = prevgraf + 1 -- the current line number being justified
- local adjust_spacing = par.adjust_spacing
- local protrude_chars = par.protrude_chars
- local statistics = par.statistics
+ local adjust_spacing = par.adjust_spacing
+ local protrude_chars = par.protrude_chars
+ local statistics = par.statistics
- local stack = new_dir_stack()
+ local stack = new_dir_stack()
- local leftskip = par.used_left_skip -- used or normal ?
- local rightskip = par.right_skip
- local parshape = par.par_shape_ptr
- ----- ignored_dimen = par.ignored_dimen
+ local leftskip = par.used_left_skip -- used or normal ?
+ local rightskip = par.right_skip
+ local parshape = par.par_shape_ptr
+ ----- ignored_dimen = par.ignored_dimen
- local adapt_width = par.adapt_width
+ local adapt_width = par.adapt_width
- -- reverse the links of the relevant passive nodes, goto first breakpoint
+ -- reverse the links of the relevant passive nodes, goto first breakpoint
- local current_break = nil
+ local current_break = nil
- local break_node = par.best_bet.break_node
- repeat
- local first_break = break_node
- break_node = break_node.prev_break
- first_break.prev_break = current_break
- current_break = first_break
- until not break_node
+ local break_node = par.best_bet.break_node
+ repeat
+ local first_break = break_node
+ break_node = break_node.prev_break
+ first_break.prev_break = current_break
+ current_break = first_break
+ until not break_node
- local head = par.head
+ local head = par.head
- -- maybe : each_...
+ -- maybe : each_...
- while current_break do
+ while current_break do
- inject_dirs_at_begin_of_line(stack,head)
+ inject_dirs_at_begin_of_line(stack,head)
- local disc_break = false
- local post_disc_break = false
- local glue_break = false
+ local disc_break = false
+ local post_disc_break = false
+ local glue_break = false
- local lineend = nil -- q lineend refers to the last node of the line (and paragraph)
- local lastnode = current_break.cur_break -- r lastnode refers to the node after which the dir nodes should be closed
+ local lineend = nil -- lineend : the last node of the line (and paragraph)
+ local lastnode = current_break.cur_break -- lastnode: the node after which the dir nodes should be closed
- if not lastnode then
- -- only at the end
- lastnode = slide_node_list(head) -- todo: find_tail
- if lastnode == par.final_par_glue then
- lineend = lastnode
- lastnode = getprev(lastnode)
- end
- else -- todo: use insert_list_after
- local id = getid(lastnode)
- if id == glue_code then
- -- lastnode is normal skip
- lastnode = replace_node(lastnode,new_rightskip(rightskip))
- glue_break = true
- lineend = lastnode
- lastnode = getprev(lastnode)
- elseif id == disc_code then
- local prevlast = getprev(lastnode)
- local nextlast = getnext(lastnode)
- local subtype = getsubtype(lastnode)
- local pre, post, replace, pretail, posttail, replacetail = getdisc(lastnode,true)
- if subtype == second_disc_code then
- if not (getid(prevlast) == disc_code and getsubtype(prevlast) == first_disc_code) then
- report_parbuilders('unsupported disc at location %a',3)
- end
- if pre then
- flush_node_list(pre)
- pre = nil -- signal
+ if not lastnode then
+ -- only at the end
+ lastnode = slide_node_list(head) -- todo: find_tail
+ if lastnode == par.final_par_glue then
+ lineend = lastnode
+ lastnode = getprev(lastnode)
+ end
+ else -- todo: use insert_list_after
+ local id = getid(lastnode)
+ if id == glue_code then
+ -- lastnode is normal skip
+ lastnode = replace_node(lastnode,new_rightskip(rightskip))
+ glue_break = true
+ lineend = lastnode
+ lastnode = getprev(lastnode)
+ elseif id == disc_code then
+ local prevlast = getprev(lastnode)
+ local nextlast = getnext(lastnode)
+ local subtype = getsubtype(lastnode)
+ local pre, post, replace, pretail, posttail, replacetail = getdisc(lastnode,true)
+ if subtype == seconddisc_code then
+ if not (getid(prevlast) == disc_code and getsubtype(prevlast) == firstdisc_code) then
+ report_parbuilders('unsupported disc at location %a',3)
+ end
+ if pre then
+ flush_node_list(pre)
+ pre = nil -- signal
+ end
+ if replace then
+ setlink(prevlast,replace)
+ setlink(replacetail,lastnode)
+ replace = nil -- signal
+ end
+ setdisc(lastnode,pre,post,replace)
+ local pre, post, replace = getdisc(prevlast)
+ if pre then
+ flush_node_list(pre)
+ end
+ if replace then
+ flush_node_list(replace)
+ end
+ if post then
+ flush_node_list(post)
+ end
+ setdisc(prevlast) -- nil,nil,nil
+ elseif subtype == firstdisc_code then
+ -- what is v ... next probably
+ if not (getid(v) == disc_code and getsubtype(v) == seconddisc_code) then
+ report_parbuilders('unsupported disc at location %a',4)
+ end
+ setsubtype(nextlast,regulardisc_code)
+ setfield(nextlast,"replace",post)
+ setfield(lastnode,"post") -- nil
end
if replace then
- setlink(prevlast,replace)
- setlink(replacetail,lastnode)
- replace = nil -- signal
+ flush_node_list(replace)
end
- setdisc(lastnode,pre,post,replace)
- local pre, post, replace = getdisc(prevlast)
if pre then
- flush_node_list(pre)
- end
- if replace then
- flush_node_list(replace)
+ setlink(prevlast,pre)
+ setlink(pretail,lastnode)
end
if post then
- flush_node_list(post)
- end
- setdisc(prevlast) -- nil,nil,nil
- elseif subtype == first_disc_code then
- -- what is v ... next probably
- if not (getid(v) == disc_code and getsubtype(v) == second_disc_code) then
- report_parbuilders('unsupported disc at location %a',4)
+ setlink(lastnode,post)
+ setlink(posttail,nextlast)
+ post_disc_break = true
end
- setsubtype(nextlast,regular_disc_code)
- setfield(nextlast,"replace",post)
- setfield(lastnode,"post") -- nil
- end
- if replace then
- flush_node_list(replace)
+ setdisc(lastnode) -- nil, nil, nil
+ disc_break = true
+ elseif id == kern_code then
+ setkern(lastnode,0)
+ elseif getid(lastnode) == math_code then
+ setkern(lastnode,0) -- surround
+ -- new in luatex
+ setglue(lastnode) -- zeros
end
- if pre then
- setlink(prevlast,pre)
- setlink(pretail,lastnode)
+ end
+ lastnode = inject_dirs_at_end_of_line(stack,lastnode,getnext(head),current_break.cur_break)
+ local rightbox = current_break.passive_right_box
+ if rightbox then
+ lastnode = insert_node_after(lastnode,lastnode,copy_node(rightbox))
+ end
+ if not lineend then
+ lineend = lastnode
+ end
+ if lineend and lineend ~= head and protrude_chars > 0 then
+ local id = getid(lineend)
+ local c = (disc_break and (id == glyph_code or id ~= disc_code) and lineend) or getprev(lineend)
+ local p = find_protchar_right(getnext(head),c)
+ if p and getid(p) == glyph_code then
+ local w, last_rightmost_char = right_pw(p)
+ if last_rightmost_char and w ~= 0 then
+ -- so we inherit attributes, lineend is new pseudo head
+ lineend, c = insert_node_after(lineend,c,new_rightmarginkern(copy_node(last_rightmost_char),-w))
+ end
end
- if post then
- setlink(lastnode,post)
- setlink(posttail,nextlast)
- post_disc_break = true
+ end
+ -- we finish the line
+ local r = getnext(lineend)
+ setnext(lineend)
+ if not glue_break then
+ if rightskip then
+ insert_node_after(lineend,lineend,new_rightskip(right_skip)) -- lineend moves on as pseudo head
end
- setdisc(lastnode) -- nil, nil, nil
- disc_break = true
- elseif id == kern_code then
- setkern(lastnode,0)
- elseif getid(lastnode) == math_code then
- setkern(lastnode,0) -- surround
- -- new in luatex
- setglue(lastnode) -- zeros
end
- end
- lastnode = inject_dirs_at_end_of_line(stack,lastnode,getnext(head),current_break.cur_break)
- local rightbox = current_break.passive_right_box
- if rightbox then
- lastnode = insert_node_after(lastnode,lastnode,copy_node(rightbox))
- end
- if not lineend then
- lineend = lastnode
- end
- if lineend and lineend ~= head and protrude_chars > 0 then
- local id = getid(lineend)
- local c = (disc_break and (id == glyph_code or id ~= disc_code) and lineend) or getprev(lineend)
- local p = find_protchar_right(getnext(head),c)
- if p and getid(p) == glyph_code then
- local w, last_rightmost_char = right_pw(p)
- if last_rightmost_char and w ~= 0 then
- -- so we inherit attributes, lineend is new pseudo head
- lineend, c = insert_node_after(lineend,c,new_rightmarginkern(copy_node(last_rightmost_char),-w))
+ -- each time ?
+ local q = getnext(head)
+ setlink(head,r)
+ -- insert leftbox (if needed after parindent)
+ local leftbox = current_break.passive_left_box
+ if leftbox then
+ local first = getnext(q)
+ if first and current_line == (par.first_line + 1) and getid(first) == hlist_code and not getlist(first) then
+ insert_node_after(q,q,copy_node(leftbox))
+ else
+ q = insert_node_before(q,q,copy_node(leftbox))
end
end
- end
- -- we finish the line
- local r = getnext(lineend)
- setnext(lineend)
- if not glue_break then
- if rightskip then
- insert_node_after(lineend,lineend,new_rightskip(right_skip)) -- lineend moves on as pseudo head
+ if protrude_chars > 0 then
+ local p = find_protchar_left(q)
+ if p and getid(p) == glyph_code then
+ local w, last_leftmost_char = left_pw(p)
+ if last_leftmost_char and w ~= 0 then
+ -- so we inherit attributes, q is pseudo head and moves back
+ q = insert_node_before(q,q,new_leftmarginkern(copy_node(last_leftmost_char),-w))
+ end
+ end
end
- end
- -- each time ?
- local q = getnext(head)
- setlink(head,r)
- -- insert leftbox (if needed after parindent)
- local leftbox = current_break.passive_left_box
- if leftbox then
- local first = getnext(q)
- if first and current_line == (par.first_line + 1) and getid(first) == hlist_code and not getlist(first) then
- insert_node_after(q,q,copy_node(leftbox))
+ if leftskip then
+ q = insert_node_before(q,q,new_leftskip(leftskip))
+ end
+ local cur_width, cur_indent
+ if current_line > par.last_special_line then
+ cur_indent = par.second_indent
+ cur_width = par.second_width
+ elseif parshape then
+ local shape = parshape[current_line]
+ cur_indent = shape[1]
+ cur_width = shape[2]
else
- q = insert_node_before(q,q,copy_node(leftbox))
- end
- end
- if protrude_chars > 0 then
- local p = find_protchar_left(q)
- if p and getid(p) == glyph_code then
- local w, last_leftmost_char = left_pw(p)
- if last_leftmost_char and w ~= 0 then
- -- so we inherit attributes, q is pseudo head and moves back
- q = insert_node_before(q,q,new_leftmarginkern(copy_node(last_leftmost_char),-w))
- end
+ cur_indent = par.first_indent
+ cur_width = par.first_width
end
- end
- if leftskip then
- q = insert_node_before(q,q,new_leftskip(leftskip))
- end
- local cur_width, cur_indent
- if current_line > par.last_special_line then
- cur_indent = par.second_indent
- cur_width = par.second_width
- elseif parshape then
- local shape = parshape[current_line]
- cur_indent = shape[1]
- cur_width = shape[2]
- else
- cur_indent = par.first_indent
- cur_width = par.first_width
- end
- if adapt_width then -- extension
- local l, r = adapt_width(par,current_line)
- cur_indent = cur_indent + l
- cur_width = cur_width - l - r
- end
+ if adapt_width then -- extension
+ local l, r = adapt_width(par,current_line)
+ cur_indent = cur_indent + l
+ cur_width = cur_width - l - r
+ end
- statistics.noflines = statistics.noflines + 1
- local finished_line = nil
- if adjust_spacing > 0 then
- statistics.nofadjustedlines = statistics.nofadjustedlines + 1
- finished_line = xpack_nodes(q,cur_width,"cal_expand_ratio",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis)
- else
- finished_line = xpack_nodes(q,cur_width,"exactly",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis)
- end
- if protrude_chars > 0 then
- statistics.nofprotrudedlines = statistics.nofprotrudedlines + 1
- end
- -- wrong:
- local adjust_head = texlists.adjust_head
- local pre_adjust_head = texlists.pre_adjust_head
- --
- setshift(finished_line,cur_indent)
- --
- -- -- this is gone:
- --
- -- if par.each_line_height ~= ignored_dimen then
- -- setheight(finished_line,par.each_line_height)
- -- end
- -- if par.each_line_depth ~= ignored_dimen then
- -- setdepth(finished_line,par.each_line_depth)
- -- end
- -- if par.first_line_height ~= ignored_dimen and (current_line == par.first_line + 1) then
- -- setheight(finished_line,par.first_line_height)
- -- end
- -- if par.last_line_depth ~= ignored_dimen and current_line + 1 == par.best_line then
- -- setdepth(finished_line,par.last_line_depth)
- -- end
- --
- if texlists.pre_adjust_head ~= pre_adjust_head then
- append_list(par, texlists.pre_adjust_head)
- texlists.pre_adjust_head = pre_adjust_head
- end
- append_to_vlist(par,finished_line)
- if texlists.adjust_head ~= adjust_head then
- append_list(par, texlists.adjust_head)
- texlists.adjust_head = adjust_head
- end
- --
- local pen
- if current_line + 1 ~= par.best_line then
- if current_break.passive_pen_inter then
- pen = current_break.passive_pen_inter
+ statistics.noflines = statistics.noflines + 1
+ local finished_line = nil
+ if adjust_spacing > 0 then
+ statistics.nofadjustedlines = statistics.nofadjustedlines + 1
+ finished_line = xpack_nodes(q,cur_width,"cal_expand_ratio",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis)
else
- pen = par.inter_line_penalty
- end
- if current_line == prevgraf + 1 then
- pen = pen + par.club_penalty
- end
- if current_line + 2 == par.best_line then
- if par.display then
- pen = pen + par.display_widow_penalty
+ finished_line = xpack_nodes(q,cur_width,"exactly",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis)
+ end
+ if protrude_chars > 0 then
+ statistics.nofprotrudedlines = statistics.nofprotrudedlines + 1
+ end
+ -- wrong:
+ local adjust_head = texlists.adjust_head
+ local pre_adjust_head = texlists.pre_adjust_head
+ --
+ setshift(finished_line,cur_indent)
+ --
+ -- -- this is gone:
+ --
+ -- if par.each_line_height ~= ignored_dimen then
+ -- setheight(finished_line,par.each_line_height)
+ -- end
+ -- if par.each_line_depth ~= ignored_dimen then
+ -- setdepth(finished_line,par.each_line_depth)
+ -- end
+ -- if par.first_line_height ~= ignored_dimen and (current_line == par.first_line + 1) then
+ -- setheight(finished_line,par.first_line_height)
+ -- end
+ -- if par.last_line_depth ~= ignored_dimen and current_line + 1 == par.best_line then
+ -- setdepth(finished_line,par.last_line_depth)
+ -- end
+ --
+ if texlists.pre_adjust_head ~= pre_adjust_head then
+ append_list(par, texlists.pre_adjust_head)
+ texlists.pre_adjust_head = pre_adjust_head
+ end
+ append_to_vlist(par,finished_line)
+ if texlists.adjust_head ~= adjust_head then
+ append_list(par, texlists.adjust_head)
+ texlists.adjust_head = adjust_head
+ end
+ --
+ local pen
+ if current_line + 1 ~= par.best_line then
+ if current_break.passive_pen_inter then
+ pen = current_break.passive_pen_inter
else
- pen = pen + par.widow_penalty
+ pen = par.inter_line_penalty
end
- end
- if disc_break then
- if current_break.passive_pen_broken ~= 0 then
- pen = pen + current_break.passive_pen_broken
- else
- pen = pen + par.broken_penalty
+ if current_line == prevgraf + 1 then
+ pen = pen + par.club_penalty
end
- end
- if pen ~= 0 then
- append_to_vlist(par,new_penalty(pen))
- end
- end
- current_line = current_line + 1
- current_break = current_break.prev_break
- if current_break and not post_disc_break then
- local current = head
- local next = nil
- while true do
- next = getnext(current)
- if next == current_break.cur_break then
- break
+ if current_line + 2 == par.best_line then
+ if par.display then
+ pen = pen + par.display_widow_penalty
+ else
+ pen = pen + par.widow_penalty
+ end
end
- local id = getid(next)
- if id == glyph_code then
- break
- elseif id == localpar_code then
- -- nothing
- elseif id < math_code then
- -- messy criterium
- break
- elseif id == math_code then
- -- keep the math node
- setkern(next,0) -- surround
- -- new in luatex
- setglue(lastnode) -- zeros
- break
- elseif id == kern_code then
- local subtype = getsubtype(next)
- if subtype == fontkern_code or subtype == accentkern_code then
- -- fontkerns and accent kerns as well as otf injections
- break
+ if disc_break then
+ if current_break.passive_pen_broken ~= 0 then
+ pen = pen + current_break.passive_pen_broken
+ else
+ pen = pen + par.broken_penalty
end
end
- current = next
+ if pen ~= 0 then
+ append_to_vlist(par,new_penalty(pen))
+ end
end
- if current ~= head then
- setnext(current)
- flush_node_list(getnext(head))
- setlink(head,next)
+ current_line = current_line + 1
+ current_break = current_break.prev_break
+ if current_break and not post_disc_break then
+ local current = head
+ local next = nil
+ while true do
+ next = getnext(current)
+ if next == current_break.cur_break then
+ break
+ end
+ local id = getid(next)
+ if id == glyph_code then
+ break
+ elseif id == localpar_code then
+ -- nothing
+ elseif id < math_code then
+ -- messy criterium
+ break
+ elseif id == math_code then
+ -- keep the math node
+ setkern(next,0) -- surround
+ -- new in luatex
+ setglue(lastnode) -- zeros
+ break
+ elseif id == kern_code then
+ local subtype = getsubtype(next)
+ if subtype == fontkern_code or subtype == accentkern_code then
+ -- fontkerns and accent kerns as well as otf injections
+ break
+ end
+ end
+ current = next
+ end
+ if current ~= head then
+ setnext(current)
+ flush_node_list(getnext(head))
+ setlink(head,next)
+ end
end
end
- end
- -- if current_line ~= par.best_line then
- -- report_parbuilders("line breaking")
- -- end
- par.head = nil -- needs checking
- current_line = current_line - 1
- if trace_basic then
- report_parbuilders("paragraph broken into %a lines",current_line)
- end
- texnest[texnest.ptr].prevgraf = current_line
-end
-
-local function wrap_up(par)
- if par.tracing_paragraphs then
- diagnostics.stop()
- end
- if par.do_last_line_fit then
- local best_bet = par.best_bet
- local active_short = best_bet.active_short
- local active_glue = best_bet.active_glue
- if active_short == 0 then
- if trace_lastlinefit then
- report_parbuilders("disabling last line fit, no active_short")
- end
- par.do_last_line_fit = false
- else
- local glue = par.final_par_glue
- setwidth(glue,getwidth(glue) + active_short - active_glue)
- setfield(glue,"stretch",0)
- if trace_lastlinefit then
- report_parbuilders("applying last line fit, short %a, glue %p",active_short,active_glue)
- end
+ -- if current_line ~= par.best_line then
+ -- report_parbuilders("line breaking")
+ -- end
+ par.head = nil -- needs checking
+ current_line = current_line - 1
+ if trace_basic then
+ report_parbuilders("paragraph broken into %a lines",current_line)
end
+ texnest[texnest.ptr].prevgraf = current_line
end
- -- we have a bunch of glue and and temp nodes not freed
- local head = par.head
- if getid(head) == temp_code then
- par.head = getnext(head)
- flush_node(head)
- end
- post_line_break(par)
- reset_meta(par)
- register_statistics(par)
- return par.head_field
-end
--- we could do active nodes differently ... table instead of linked list or a list
--- with prev nodes but it doesn't save much (as we still need to keep indices then
--- in next)
-
-local function deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion) -- no need for adjust if disabled
- local active = par.active
- local active_width = par.active_width
- prev_r.next = r.next
- -- removes r
- -- r = nil
- if prev_r == active then
- r = active.next
- if r.id == delta_code then
- local aw = active_width.size + r.size active_width.size = aw cur_active_width.size = aw
- local aw = active_width.stretch + r.stretch active_width.stretch = aw cur_active_width.stretch = aw
- local aw = active_width.fi + r.fi active_width.fi = aw cur_active_width.fi = aw
- local aw = active_width.fil + r.fil active_width.fil = aw cur_active_width.fil = aw
- local aw = active_width.fill + r.fill active_width.fill = aw cur_active_width.fill = aw
- local aw = active_width.filll + r.filll active_width.filll = aw cur_active_width.filll = aw
- local aw = active_width.shrink + r.shrink active_width.shrink = aw cur_active_width.shrink = aw
- if checked_expansion then
- local aw = active_width.adjust_stretch + r.adjust_stretch active_width.adjust_stretch = aw cur_active_width.adjust_stretch = aw
- local aw = active_width.adjust_shrink + r.adjust_shrink active_width.adjust_shrink = aw cur_active_width.adjust_shrink = aw
- end
- active.next = r.next
- -- removes r
- -- r = nil
+ local function wrap_up(par)
+ if par.tracing_paragraphs then
+ diagnostics.stop()
end
- elseif prev_r.id == delta_code then
- r = prev_r.next
- if r == active then
- cur_active_width.size = cur_active_width.size - prev_r.size
- cur_active_width.stretch = cur_active_width.stretch - prev_r.stretch
- cur_active_width.fi = cur_active_width.fi - prev_r.fi
- cur_active_width.fil = cur_active_width.fil - prev_r.fil
- cur_active_width.fill = cur_active_width.fill - prev_r.fill
- cur_active_width.filll = cur_active_width.filll - prev_r.filll
- cur_active_width.shrink = cur_active_width.shrink - prev_r.shrink
- if checked_expansion then
- cur_active_width.adjust_stretch = cur_active_width.adjust_stretch - prev_r.adjust_stretch
- cur_active_width.adjust_shrink = cur_active_width.adjust_shrink - prev_r.adjust_shrink
+ if par.do_last_line_fit then
+ local best_bet = par.best_bet
+ local active_short = best_bet.active_short
+ local active_glue = best_bet.active_glue
+ if active_short == 0 then
+ if trace_lastlinefit then
+ report_parbuilders("disabling last line fit, no active_short")
+ end
+ par.do_last_line_fit = false
+ else
+ local glue = par.final_par_glue
+ setwidth(glue,getwidth(glue) + active_short - active_glue)
+ setfield(glue,"stretch",0)
+ if trace_lastlinefit then
+ report_parbuilders("applying last line fit, short %a, glue %p",active_short,active_glue)
+ end
end
- prev_prev_r.next = active
- -- removes prev_r
- -- prev_r = nil
- prev_r = prev_prev_r
- elseif r.id == delta_code then
- local rn = r.size cur_active_width.size = cur_active_width.size + rn prev_r.size = prev_r.size + rn
- local rn = r.stretch cur_active_width.stretch = cur_active_width.stretch + rn prev_r.stretch = prev_r.stretch + rn
- local rn = r.fi cur_active_width.fi = cur_active_width.fi + rn prev_r.fi = prev_r.fi + rn
- local rn = r.fil cur_active_width.fil = cur_active_width.fil + rn prev_r.fil = prev_r.fil + rn
- local rn = r.fill cur_active_width.fill = cur_active_width.fill + rn prev_r.fill = prev_r.fill + rn
- local rn = r.filll cur_active_width.filll = cur_active_width.filll + rn prev_r.filll = prev_r.fill + rn
- local rn = r.shrink cur_active_width.shrink = cur_active_width.shrink + rn prev_r.shrink = prev_r.shrink + rn
- if checked_expansion then
- local rn = r.adjust_stretch cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + rn prev_r.adjust_stretch = prev_r.adjust_stretch + rn
- local rn = r.adjust_shrink cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + rn prev_r.adjust_shrink = prev_r.adjust_shrink + rn
+ end
+ -- we have a bunch of glue and and temp nodes not freed
+ local head = par.head
+ if getid(head) == temp_code then
+ par.head = getnext(head)
+ flush_node(head)
+ end
+ post_line_break(par)
+ reset_meta(par)
+ register_statistics(par)
+ return par.head_field
+ end
+
+ -- we could do active nodes differently ... table instead of linked list or a list
+ -- with prev nodes but it doesn't save much (as we still need to keep indices then
+ -- in next)
+
+ local function deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion) -- no need for adjust if disabled
+ local active = par.active
+ local active_width = par.active_width
+ prev_r.next = r.next
+ -- removes r
+ -- r = nil
+ if prev_r == active then
+ r = active.next
+ if r.id == delta_code then
+ local aw = active_width.size + r.size active_width.size = aw cur_active_width.size = aw
+ local aw = active_width.stretch + r.stretch active_width.stretch = aw cur_active_width.stretch = aw
+ local aw = active_width.fi + r.fi active_width.fi = aw cur_active_width.fi = aw
+ local aw = active_width.fil + r.fil active_width.fil = aw cur_active_width.fil = aw
+ local aw = active_width.fill + r.fill active_width.fill = aw cur_active_width.fill = aw
+ local aw = active_width.filll + r.filll active_width.filll = aw cur_active_width.filll = aw
+ local aw = active_width.shrink + r.shrink active_width.shrink = aw cur_active_width.shrink = aw
+ if checked_expansion then
+ local aw = active_width.adjust_stretch + r.adjust_stretch active_width.adjust_stretch = aw cur_active_width.adjust_stretch = aw
+ local aw = active_width.adjust_shrink + r.adjust_shrink active_width.adjust_shrink = aw cur_active_width.adjust_shrink = aw
+ end
+ active.next = r.next
+ -- removes r
+ -- r = nil
+ end
+ elseif prev_r.id == delta_code then
+ r = prev_r.next
+ if r == active then
+ cur_active_width.size = cur_active_width.size - prev_r.size
+ cur_active_width.stretch = cur_active_width.stretch - prev_r.stretch
+ cur_active_width.fi = cur_active_width.fi - prev_r.fi
+ cur_active_width.fil = cur_active_width.fil - prev_r.fil
+ cur_active_width.fill = cur_active_width.fill - prev_r.fill
+ cur_active_width.filll = cur_active_width.filll - prev_r.filll
+ cur_active_width.shrink = cur_active_width.shrink - prev_r.shrink
+ if checked_expansion then
+ cur_active_width.adjust_stretch = cur_active_width.adjust_stretch - prev_r.adjust_stretch
+ cur_active_width.adjust_shrink = cur_active_width.adjust_shrink - prev_r.adjust_shrink
+ end
+ prev_prev_r.next = active
+ -- removes prev_r
+ -- prev_r = nil
+ prev_r = prev_prev_r
+ elseif r.id == delta_code then
+ local rn = r.size cur_active_width.size = cur_active_width.size + rn prev_r.size = prev_r.size + rn
+ local rn = r.stretch cur_active_width.stretch = cur_active_width.stretch + rn prev_r.stretch = prev_r.stretch + rn
+ local rn = r.fi cur_active_width.fi = cur_active_width.fi + rn prev_r.fi = prev_r.fi + rn
+ local rn = r.fil cur_active_width.fil = cur_active_width.fil + rn prev_r.fil = prev_r.fil + rn
+ local rn = r.fill cur_active_width.fill = cur_active_width.fill + rn prev_r.fill = prev_r.fill + rn
+ local rn = r.filll cur_active_width.filll = cur_active_width.filll + rn prev_r.filll = prev_r.fill + rn
+ local rn = r.shrink cur_active_width.shrink = cur_active_width.shrink + rn prev_r.shrink = prev_r.shrink + rn
+ if checked_expansion then
+ local rn = r.adjust_stretch cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + rn prev_r.adjust_stretch = prev_r.adjust_stretch + rn
+ local rn = r.adjust_shrink cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + rn prev_r.adjust_shrink = prev_r.adjust_shrink + rn
+ end
+ prev_r.next = r.next
+ -- removes r
+ -- r = nil
end
- prev_r.next = r.next
- -- removes r
- -- r = nil
end
+ return prev_r, r
end
- return prev_r, r
-end
-local function lastlinecrap(shortfall,active_short,active_glue,cur_active_width,fill_width,last_line_fit)
- if active_short == 0 or active_glue <= 0 then
- return false, 0, fit_decent_class, 0, 0
- end
- if cur_active_width.fi ~= fill_width.fi or cur_active_width.fil ~= fill_width.fil or cur_active_width.fill ~= fill_width.fill or cur_active_width.filll ~= fill_width.filll then
- return false, 0, fit_decent_class, 0, 0
- end
- local adjustment = active_short > 0 and cur_active_width.stretch or cur_active_width.shrink
- if adjustment <= 0 then
- return false, 0, fit_decent_class, adjustment, 0
- end
- adjustment = calculate_fraction(adjustment,active_short,active_glue,maxdimen)
- if last_line_fit < 1000 then
- adjustment = calculate_fraction(adjustment,last_line_fit,1000,maxdimen) -- uses previous adjustment
- end
- local fit_class = fit_decent_class
- if adjustment > 0 then
- local stretch = cur_active_width.stretch
- if adjustment > shortfall then
- adjustment = shortfall
- end
- if adjustment > 7230584 and stretch < 1663497 then
- return true, fit_very_loose_class, shortfall, adjustment, infinite_badness
+ local function lastlinecrap(shortfall,active_short,active_glue,cur_active_width,fill_width,last_line_fit)
+ if active_short == 0 or active_glue <= 0 then
+ return false, 0, fit_decent_class, 0, 0
end
- -- if adjustment == 0 then -- badness = 0
- -- return true, shortfall, fit_decent_class, 0, 0
- -- elseif stretch <= 0 then -- badness = 10000
- -- return true, shortfall, fit_very_loose_class, adjustment, 10000
- -- end
- -- local badness = (adjustment == 0 and 0) or (stretch <= 0 and 10000) or calculate_badness(adjustment,stretch)
- local badness = calculate_badness(adjustment,stretch)
- if badness > 99 then
- return true, shortfall, fit_very_loose_class, adjustment, badness
- elseif badness > 12 then
- return true, shortfall, fit_loose_class, adjustment, badness
- else
- return true, shortfall, fit_decent_class, adjustment, badness
+ if cur_active_width.fi ~= fill_width.fi or cur_active_width.fil ~= fill_width.fil or cur_active_width.fill ~= fill_width.fill or cur_active_width.filll ~= fill_width.filll then
+ return false, 0, fit_decent_class, 0, 0
end
- elseif adjustment < 0 then
- local shrink = cur_active_width.shrink
- if -adjustment > shrink then
- adjustment = -shrink
+ local adjustment = active_short > 0 and cur_active_width.stretch or cur_active_width.shrink
+ if adjustment <= 0 then
+ return false, 0, fit_decent_class, adjustment, 0
end
- local badness = calculate_badness(-adjustment,shrink)
- if badness > 12 then
- return true, shortfall, fit_tight_class, adjustment, badness
- else
- return true, shortfall, fit_decent_class, adjustment, badness
+ adjustment = calculate_fraction(adjustment,active_short,active_glue,maxdimen)
+ if last_line_fit < 1000 then
+ adjustment = calculate_fraction(adjustment,last_line_fit,1000,maxdimen) -- uses previous adjustment
end
- else
- return false, 0, fit_decent_class, 0, 0
- end
-end
-
--- todo: statistics .. count tries and so
-
-local trialcount = 0
-
-local function try_break(pi, break_type, par, first_p, current, checked_expansion)
-
--- trialcount = trialcount + 1
--- print(trialcount,pi,break_type,current,nuts.tostring(current))
-
- if pi >= infinite_penalty then -- this breakpoint is inhibited by infinite penalty
- local p_active = par.active
- return p_active, p_active and p_active.next
- elseif pi <= -infinite_penalty then -- this breakpoint will be forced
- pi = eject_penalty
- end
-
- local prev_prev_r = nil -- a step behind prev_r, if type(prev_r)=delta_code
- local prev_r = par.active -- stays a step behind r
- local r = nil -- runs through the active list
- local no_break_yet = true -- have we found a feasible break at current?
- local node_r_stays_active = false -- should node r remain in the active list?
- local line_width = 0 -- the current line will be justified to this width
- local line_number = 0 -- line number of current active node
- local old_line_number = 0 -- maximum line number in current equivalence class of lines
-
- local protrude_chars = par.protrude_chars
- local checked_expansion = par.checked_expansion
- local break_width = par.break_width
- local active_width = par.active_width
- local background = par.background
- local minimal_demerits = par.minimal_demerits
- local best_place = par.best_place
- local best_pl_line = par.best_pl_line
- local best_pl_short = par.best_pl_short
- local best_pl_glue = par.best_pl_glue
- local do_last_line_fit = par.do_last_line_fit
- local final_pass = par.final_pass
- local tracing_paragraphs = par.tracing_paragraphs
- -- local par_active = par.active
-
- local adapt_width = par.adapt_width
-
- local parshape = par.par_shape_ptr
-
- local cur_active_width = checked_expansion and { -- distance from current active node
- size = active_width.size,
- stretch = active_width.stretch,
- fi = active_width.fi,
- fil = active_width.fil,
- fill = active_width.fill,
- filll = active_width.filll,
- shrink = active_width.shrink,
- adjust_stretch = active_width.adjust_stretch,
- adjust_shrink = active_width.adjust_shrink,
- } or {
- size = active_width.size,
- stretch = active_width.stretch,
- fi = active_width.fi,
- fil = active_width.fil,
- fill = active_width.fill,
- filll = active_width.filll,
- shrink = active_width.shrink,
- }
-
- while true do
- r = prev_r.next
- if r.id == delta_code then
- cur_active_width.size = cur_active_width.size + r.size
- cur_active_width.stretch = cur_active_width.stretch + r.stretch
- cur_active_width.fi = cur_active_width.fi + r.fi
- cur_active_width.fil = cur_active_width.fil + r.fil
- cur_active_width.fill = cur_active_width.fill + r.fill
- cur_active_width.filll = cur_active_width.filll + r.filll
- cur_active_width.shrink = cur_active_width.shrink + r.shrink
- if checked_expansion then
- cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + r.adjust_stretch
- cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + r.adjust_shrink
+ local fit_class = fit_decent_class
+ if adjustment > 0 then
+ local stretch = cur_active_width.stretch
+ if adjustment > shortfall then
+ adjustment = shortfall
+ end
+ if adjustment > 7230584 and stretch < 1663497 then
+ return true, fit_very_loose_class, shortfall, adjustment, infinite_badness
+ end
+ -- if adjustment == 0 then -- badness = 0
+ -- return true, shortfall, fit_decent_class, 0, 0
+ -- elseif stretch <= 0 then -- badness = 10000
+ -- return true, shortfall, fit_very_loose_class, adjustment, 10000
+ -- end
+ -- local badness = (adjustment == 0 and 0) or (stretch <= 0 and 10000) or calculate_badness(adjustment,stretch)
+ local badness = calculate_badness(adjustment,stretch)
+ if badness > 99 then
+ return true, shortfall, fit_very_loose_class, adjustment, badness
+ elseif badness > 12 then
+ return true, shortfall, fit_loose_class, adjustment, badness
+ else
+ return true, shortfall, fit_decent_class, adjustment, badness
+ end
+ elseif adjustment < 0 then
+ local shrink = cur_active_width.shrink
+ if -adjustment > shrink then
+ adjustment = -shrink
+ end
+ local badness = calculate_badness(-adjustment,shrink)
+ if badness > 12 then
+ return true, shortfall, fit_tight_class, adjustment, badness
+ else
+ return true, shortfall, fit_decent_class, adjustment, badness
end
- prev_prev_r = prev_r
- prev_r = r
else
- line_number = r.line_number
- if line_number > old_line_number then
- local minimum_demerits = par.minimum_demerits
- if minimum_demerits < awful_badness and (old_line_number ~= par.easy_line or r == par.active) then
- if no_break_yet then
- no_break_yet = false
- break_width.size = background.size
- break_width.stretch = background.stretch
- break_width.fi = background.fi
- break_width.fil = background.fil
- break_width.fill = background.fill
- break_width.filll = background.filll
- break_width.shrink = background.shrink
- if checked_expansion then
- break_width.adjust_stretch = 0
- break_width.adjust_shrink = 0
+ return false, 0, fit_decent_class, 0, 0
+ end
+ end
+
+ -- todo: statistics .. count tries and so
+
+ local trialcount = 0
+
+ local function try_break(pi, break_type, par, first_p, current, checked_expansion)
+
+ -- trialcount = trialcount + 1
+ -- print(trialcount,pi,break_type,current,nuts.tostring(current))
+
+ if pi >= infinite_penalty then -- this breakpoint is inhibited by infinite penalty
+ local p_active = par.active
+ return p_active, p_active and p_active.next
+ elseif pi <= -infinite_penalty then -- this breakpoint will be forced
+ pi = eject_penalty
+ end
+
+ local prev_prev_r = nil -- a step behind prev_r, if type(prev_r)=delta_code
+ local prev_r = par.active -- stays a step behind r
+ local r = nil -- runs through the active list
+ local no_break_yet = true -- have we found a feasible break at current?
+ local node_r_stays_active = false -- should node r remain in the active list?
+ local line_width = 0 -- the current line will be justified to this width
+ local line_number = 0 -- line number of current active node
+ local old_line_number = 0 -- maximum line number in current equivalence class of lines
+
+ local protrude_chars = par.protrude_chars
+ local checked_expansion = par.checked_expansion
+ local break_width = par.break_width
+ local active_width = par.active_width
+ local background = par.background
+ local minimal_demerits = par.minimal_demerits
+ local best_place = par.best_place
+ local best_pl_line = par.best_pl_line
+ local best_pl_short = par.best_pl_short
+ local best_pl_glue = par.best_pl_glue
+ local do_last_line_fit = par.do_last_line_fit
+ local final_pass = par.final_pass
+ local tracing_paragraphs = par.tracing_paragraphs
+ -- local par_active = par.active
+
+ local adapt_width = par.adapt_width
+
+ local parshape = par.par_shape_ptr
+
+ local cur_active_width = checked_expansion and { -- distance from current active node
+ size = active_width.size,
+ stretch = active_width.stretch,
+ fi = active_width.fi,
+ fil = active_width.fil,
+ fill = active_width.fill,
+ filll = active_width.filll,
+ shrink = active_width.shrink,
+ adjust_stretch = active_width.adjust_stretch,
+ adjust_shrink = active_width.adjust_shrink,
+ } or {
+ size = active_width.size,
+ stretch = active_width.stretch,
+ fi = active_width.fi,
+ fil = active_width.fil,
+ fill = active_width.fill,
+ filll = active_width.filll,
+ shrink = active_width.shrink,
+ }
+
+ while true do
+ r = prev_r.next
+ if r.id == delta_code then
+ cur_active_width.size = cur_active_width.size + r.size
+ cur_active_width.stretch = cur_active_width.stretch + r.stretch
+ cur_active_width.fi = cur_active_width.fi + r.fi
+ cur_active_width.fil = cur_active_width.fil + r.fil
+ cur_active_width.fill = cur_active_width.fill + r.fill
+ cur_active_width.filll = cur_active_width.filll + r.filll
+ cur_active_width.shrink = cur_active_width.shrink + r.shrink
+ if checked_expansion then
+ cur_active_width.adjust_stretch = cur_active_width.adjust_stretch + r.adjust_stretch
+ cur_active_width.adjust_shrink = cur_active_width.adjust_shrink + r.adjust_shrink
+ end
+ prev_prev_r = prev_r
+ prev_r = r
+ else
+ line_number = r.line_number
+ if line_number > old_line_number then
+ local minimum_demerits = par.minimum_demerits
+ if minimum_demerits < awful_badness and (old_line_number ~= par.easy_line or r == par.active) then
+ if no_break_yet then
+ no_break_yet = false
+ break_width.size = background.size
+ break_width.stretch = background.stretch
+ break_width.fi = background.fi
+ break_width.fil = background.fil
+ break_width.fill = background.fill
+ break_width.filll = background.filll
+ break_width.shrink = background.shrink
+ if checked_expansion then
+ break_width.adjust_stretch = 0
+ break_width.adjust_shrink = 0
+ end
+ if current then
+ compute_break_width(par,break_type,current)
+ end
end
- if current then
- compute_break_width(par,break_type,current)
+ if prev_r.id == delta_code then
+ prev_r.size = prev_r.size - cur_active_width.size + break_width.size
+ prev_r.stretch = prev_r.stretch - cur_active_width.stretc + break_width.stretch
+ prev_r.fi = prev_r.fi - cur_active_width.fi + break_width.fi
+ prev_r.fil = prev_r.fil - cur_active_width.fil + break_width.fil
+ prev_r.fill = prev_r.fill - cur_active_width.fill + break_width.fill
+ prev_r.filll = prev_r.filll - cur_active_width.filll + break_width.filll
+ prev_r.shrink = prev_r.shrink - cur_active_width.shrink + break_width.shrink
+ if checked_expansion then
+ prev_r.adjust_stretch = prev_r.adjust_stretch - cur_active_width.adjust_stretch + break_width.adjust_stretch
+ prev_r.adjust_shrink = prev_r.adjust_shrink - cur_active_width.adjust_shrink + break_width.adjust_shrink
+ end
+ elseif prev_r == par.active then
+ active_width.size = break_width.size
+ active_width.stretch = break_width.stretch
+ active_width.fi = break_width.fi
+ active_width.fil = break_width.fil
+ active_width.fill = break_width.fill
+ active_width.filll = break_width.filll
+ active_width.shrink = break_width.shrink
+ if checked_expansion then
+ active_width.adjust_stretch = break_width.adjust_stretch
+ active_width.adjust_shrink = break_width.adjust_shrink
+ end
+ else
+ local q = checked_expansion and {
+ id = delta_code,
+ subtype = nosubtype_code,
+ next = r,
+ size = break_width.size - cur_active_width.size,
+ stretch = break_width.stretch - cur_active_width.stretch,
+ fi = break_width.fi - cur_active_width.fi,
+ fil = break_width.fil - cur_active_width.fil,
+ fill = break_width.fill - cur_active_width.fill,
+ filll = break_width.filll - cur_active_width.filll,
+ shrink = break_width.shrink - cur_active_width.shrink,
+ adjust_stretch = break_width.adjust_stretch - cur_active_width.adjust_stretch,
+ adjust_shrink = break_width.adjust_shrink - cur_active_width.adjust_shrink,
+ } or {
+ id = delta_code,
+ subtype = nosubtype_code,
+ next = r,
+ size = break_width.size - cur_active_width.size,
+ stretch = break_width.stretch - cur_active_width.stretch,
+ fi = break_width.fi - cur_active_width.fi,
+ fil = break_width.fil - cur_active_width.fil,
+ fill = break_width.fill - cur_active_width.fill,
+ filll = break_width.filll - cur_active_width.filll,
+ shrink = break_width.shrink - cur_active_width.shrink,
+ }
+ prev_r.next = q
+ prev_prev_r = prev_r
+ prev_r = q
end
- end
- if prev_r.id == delta_code then
- prev_r.size = prev_r.size - cur_active_width.size + break_width.size
- prev_r.stretch = prev_r.stretch - cur_active_width.stretc + break_width.stretch
- prev_r.fi = prev_r.fi - cur_active_width.fi + break_width.fi
- prev_r.fil = prev_r.fil - cur_active_width.fil + break_width.fil
- prev_r.fill = prev_r.fill - cur_active_width.fill + break_width.fill
- prev_r.filll = prev_r.filll - cur_active_width.filll + break_width.filll
- prev_r.shrink = prev_r.shrink - cur_active_width.shrink + break_width.shrink
- if checked_expansion then
- prev_r.adjust_stretch = prev_r.adjust_stretch - cur_active_width.adjust_stretch + break_width.adjust_stretch
- prev_r.adjust_shrink = prev_r.adjust_shrink - cur_active_width.adjust_shrink + break_width.adjust_shrink
+ local adj_demerits = par.adj_demerits
+ local abs_adj_demerits = adj_demerits > 0 and adj_demerits or -adj_demerits
+ if abs_adj_demerits >= awful_badness - minimum_demerits then
+ minimum_demerits = awful_badness - 1
+ else
+ minimum_demerits = minimum_demerits + abs_adj_demerits
end
- elseif prev_r == par.active then
- active_width.size = break_width.size
- active_width.stretch = break_width.stretch
- active_width.fi = break_width.fi
- active_width.fil = break_width.fil
- active_width.fill = break_width.fill
- active_width.filll = break_width.filll
- active_width.shrink = break_width.shrink
- if checked_expansion then
- active_width.adjust_stretch = break_width.adjust_stretch
- active_width.adjust_shrink = break_width.adjust_shrink
+ for fit_class = fit_very_loose_class, fit_tight_class do
+ if minimal_demerits[fit_class] <= minimum_demerits then
+ -- insert a new active node from best_place[fit_class] to current
+ par.pass_number = par.pass_number + 1
+ local prev_break = best_place[fit_class]
+ local passive = {
+ id = passive_code,
+ subtype = nosubtype_code,
+ next = par.passive,
+ cur_break = current,
+ serial = par.pass_number,
+ prev_break = prev_break,
+ passive_pen_inter = par.internal_pen_inter,
+ passive_pen_broken = par.internal_pen_broken,
+ passive_last_left_box = par.internal_left_box,
+ passive_last_left_box_width = par.internal_left_box_width,
+ passive_left_box = prev_break and prev_break.passive_last_left_box or par.init_internal_left_box,
+ passive_left_box_width = prev_break and prev_break.passive_last_left_box_width or par.init_internal_left_box_width,
+ passive_right_box = par.internal_right_box,
+ passive_right_box_width = par.internal_right_box_width,
+ -- analysis = table.fastcopy(cur_active_width),
+ }
+ par.passive = passive
+ local q = {
+ id = break_type,
+ subtype = fit_class,
+ break_node = passive,
+ line_number = best_pl_line[fit_class] + 1,
+ total_demerits = minimal_demerits[fit_class], -- or 0,
+ next = r,
+ }
+ if do_last_line_fit then
+ local active_short = best_pl_short[fit_class]
+ local active_glue = best_pl_glue[fit_class]
+ q.active_short = active_short
+ q.active_glue = active_glue
+ if trace_lastlinefit then
+ report_parbuilders("setting short to %i and glue to %p using class %a",active_short,active_glue,fit_class)
+ end
+ end
+ -- q.next = r -- already done
+ prev_r.next = q
+ prev_r = q
+ if tracing_paragraphs then
+ diagnostics.break_node(par,q,fit_class,break_type,current)
+ end
+ end
+ minimal_demerits[fit_class] = awful_badness
end
- else
- local q = checked_expansion and {
- id = delta_code,
- subtype = nosubtype_code,
- next = r,
- size = break_width.size - cur_active_width.size,
- stretch = break_width.stretch - cur_active_width.stretch,
- fi = break_width.fi - cur_active_width.fi,
- fil = break_width.fil - cur_active_width.fil,
- fill = break_width.fill - cur_active_width.fill,
- filll = break_width.filll - cur_active_width.filll,
- shrink = break_width.shrink - cur_active_width.shrink,
- adjust_stretch = break_width.adjust_stretch - cur_active_width.adjust_stretch,
- adjust_shrink = break_width.adjust_shrink - cur_active_width.adjust_shrink,
- } or {
- id = delta_code,
- subtype = nosubtype_code,
- next = r,
- size = break_width.size - cur_active_width.size,
- stretch = break_width.stretch - cur_active_width.stretch,
- fi = break_width.fi - cur_active_width.fi,
- fil = break_width.fil - cur_active_width.fil,
- fill = break_width.fill - cur_active_width.fill,
- filll = break_width.filll - cur_active_width.filll,
- shrink = break_width.shrink - cur_active_width.shrink,
- }
- prev_r.next = q
- prev_prev_r = prev_r
- prev_r = q
- end
- local adj_demerits = par.adj_demerits
- local abs_adj_demerits = adj_demerits > 0 and adj_demerits or -adj_demerits
- if abs_adj_demerits >= awful_badness - minimum_demerits then
- minimum_demerits = awful_badness - 1
- else
- minimum_demerits = minimum_demerits + abs_adj_demerits
- end
- for fit_class = fit_very_loose_class, fit_tight_class do
- if minimal_demerits[fit_class] <= minimum_demerits then
- -- insert a new active node from best_place[fit_class] to current
- par.pass_number = par.pass_number + 1
- local prev_break = best_place[fit_class]
- local passive = {
- id = passive_code,
- subtype = nosubtype_code,
- next = par.passive,
- cur_break = current,
- serial = par.pass_number,
- prev_break = prev_break,
- passive_pen_inter = par.internal_pen_inter,
- passive_pen_broken = par.internal_pen_broken,
- passive_last_left_box = par.internal_left_box,
- passive_last_left_box_width = par.internal_left_box_width,
- passive_left_box = prev_break and prev_break.passive_last_left_box or par.init_internal_left_box,
- passive_left_box_width = prev_break and prev_break.passive_last_left_box_width or par.init_internal_left_box_width,
- passive_right_box = par.internal_right_box,
- passive_right_box_width = par.internal_right_box_width,
--- analysis = table.fastcopy(cur_active_width),
- }
- par.passive = passive
- local q = {
- id = break_type,
- subtype = fit_class,
- break_node = passive,
- line_number = best_pl_line[fit_class] + 1,
- total_demerits = minimal_demerits[fit_class], -- or 0,
+ par.minimum_demerits = awful_badness
+ if r ~= par.active then
+ local q = checked_expansion and {
+ id = delta_code,
+ subtype = nosubtype_code,
+ next = r,
+ size = cur_active_width.size - break_width.size,
+ stretch = cur_active_width.stretch - break_width.stretch,
+ fi = cur_active_width.fi - break_width.fi,
+ fil = cur_active_width.fil - break_width.fil,
+ fill = cur_active_width.fill - break_width.fill,
+ filll = cur_active_width.filll - break_width.filll,
+ shrink = cur_active_width.shrink - break_width.shrink,
+ adjust_stretch = cur_active_width.adjust_stretch - break_width.adjust_stretch,
+ adjust_shrink = cur_active_width.adjust_shrink - break_width.adjust_shrink,
+ } or {
+ id = delta_code,
+ subtype = nosubtype_code,
next = r,
+ size = cur_active_width.size - break_width.size,
+ stretch = cur_active_width.stretch - break_width.stretch,
+ fi = cur_active_width.fi - break_width.fi,
+ fil = cur_active_width.fil - break_width.fil,
+ fill = cur_active_width.fill - break_width.fill,
+ filll = cur_active_width.filll - break_width.filll,
+ shrink = cur_active_width.shrink - break_width.shrink,
}
- if do_last_line_fit then
- local active_short = best_pl_short[fit_class]
- local active_glue = best_pl_glue[fit_class]
- q.active_short = active_short
- q.active_glue = active_glue
- if trace_lastlinefit then
- report_parbuilders("setting short to %i and glue to %p using class %a",active_short,active_glue,fit_class)
- end
- end
-- q.next = r -- already done
prev_r.next = q
+ prev_prev_r = prev_r
prev_r = q
- if tracing_paragraphs then
- diagnostics.break_node(par,q,fit_class,break_type,current)
- end
end
- minimal_demerits[fit_class] = awful_badness
- end
- par.minimum_demerits = awful_badness
- if r ~= par.active then
- local q = checked_expansion and {
- id = delta_code,
- subtype = nosubtype_code,
- next = r,
- size = cur_active_width.size - break_width.size,
- stretch = cur_active_width.stretch - break_width.stretch,
- fi = cur_active_width.fi - break_width.fi,
- fil = cur_active_width.fil - break_width.fil,
- fill = cur_active_width.fill - break_width.fill,
- filll = cur_active_width.filll - break_width.filll,
- shrink = cur_active_width.shrink - break_width.shrink,
- adjust_stretch = cur_active_width.adjust_stretch - break_width.adjust_stretch,
- adjust_shrink = cur_active_width.adjust_shrink - break_width.adjust_shrink,
- } or {
- id = delta_code,
- subtype = nosubtype_code,
- next = r,
- size = cur_active_width.size - break_width.size,
- stretch = cur_active_width.stretch - break_width.stretch,
- fi = cur_active_width.fi - break_width.fi,
- fil = cur_active_width.fil - break_width.fil,
- fill = cur_active_width.fill - break_width.fill,
- filll = cur_active_width.filll - break_width.filll,
- shrink = cur_active_width.shrink - break_width.shrink,
- }
- -- q.next = r -- already done
- prev_r.next = q
- prev_prev_r = prev_r
- prev_r = q
end
- end
- if r == par.active then
- return r, r and r.next -- p_active, n_active
- end
- if line_number > par.easy_line then
- old_line_number = max_halfword - 1
- line_width = par.second_width
- else
- old_line_number = line_number
- if line_number > par.last_special_line then
+ if r == par.active then
+ return r, r and r.next -- p_active, n_active
+ end
+ if line_number > par.easy_line then
+ old_line_number = max_halfword - 1
line_width = par.second_width
- elseif parshape then
- line_width = parshape[line_number][2]
else
- line_width = par.first_width
+ old_line_number = line_number
+ if line_number > par.last_special_line then
+ line_width = par.second_width
+ elseif parshape then
+ line_width = parshape[line_number][2]
+ else
+ line_width = par.first_width
+ end
end
- end
- if adapt_width then
- local l, r = adapt_width(par,line_number)
- line_width = line_width - l - r
- end
- end
- local artificial_demerits = false -- has d been forced to zero
- local shortfall = line_width - cur_active_width.size - par.internal_right_box_width -- used in badness calculations
- if not r.break_node then
- shortfall = shortfall - par.init_internal_left_box_width
- else
- shortfall = shortfall - (r.break_node.passive_last_left_box_width or 0)
- end
- local pw, lp, rp -- used later on
- if protrude_chars > 1 then
- -- this is quite time consuming
- local b = r.break_node
- local l = b and b.cur_break or first_p
- local o = current and getprev(current)
- if current and getid(current) == disc_code then
- local pre, _, _, pretail = getdisc(current,true)
- if pre then
- o = pretail
- else
- o = find_protchar_right(l,o)
+ if adapt_width then
+ local l, r = adapt_width(par,line_number)
+ line_width = line_width - l - r
end
- else
- o = find_protchar_right(l,o)
end
- if o and getid(o) == glyph_code then
- pw, rp = right_pw(o)
- shortfall = shortfall + pw
- end
- local id = getid(l)
- if id == glyph_code then
- -- ok ?
- elseif id == disc_code and getfield(l,"post") then
- l = getfield(l,"post") -- TODO: first char could be a disc
+ local artificial_demerits = false -- has d been forced to zero
+ local shortfall = line_width - cur_active_width.size - par.internal_right_box_width -- used in badness calculations
+ if not r.break_node then
+ shortfall = shortfall - par.init_internal_left_box_width
else
- l = find_protchar_left(l)
- end
- if l and getid(l) == glyph_code then
- pw, lp = left_pw(l)
- shortfall = shortfall + pw
+ shortfall = shortfall - (r.break_node.passive_last_left_box_width or 0)
end
- end
- if checked_expansion and shortfall ~= 0 then
- local margin_kern_stretch = 0
- local margin_kern_shrink = 0
+ local pw, lp, rp -- used later on
if protrude_chars > 1 then
- if lp then
- local data = expansions[getfont(lp)][getchar(lp)]
- if data then
- margin_kern_stretch, margin_kern_shrink = data.glyphstretch, data.glyphshrink
+ -- this is quite time consuming
+ local b = r.break_node
+ local l = b and b.cur_break or first_p
+ local o = current and getprev(current)
+ if current and getid(current) == disc_code then
+ local pre, _, _, pretail = getdisc(current,true)
+ if pre then
+ o = pretail
+ else
+ o = find_protchar_right(l,o)
end
+ else
+ o = find_protchar_right(l,o)
end
- if rp then
- local data = expansions[getfont(lp)][getchar(lp)]
- if data then
- margin_kern_stretch = margin_kern_stretch + data.glyphstretch
- margin_kern_shrink = margin_kern_shrink + data.glyphshrink
- end
+ if o and getid(o) == glyph_code then
+ pw, rp = right_pw(o)
+ shortfall = shortfall + pw
end
- end
- local total = cur_active_width.adjust_stretch + margin_kern_stretch
- if shortfall > 0 and total > 0 then
- if total > shortfall then
- shortfall = total / (par.max_stretch_ratio / par.cur_font_step) / 2
+ local id = getid(l)
+ if id == glyph_code then
+ -- ok ?
+ elseif id == disc_code and getfield(l,"post") then
+ l = getfield(l,"post") -- TODO: first char could be a disc
else
- shortfall = shortfall - total
+ l = find_protchar_left(l)
end
- else
- total = cur_active_width.adjust_shrink + margin_kern_shrink
- if shortfall < 0 and total > 0 then
- if total > - shortfall then
- shortfall = - total / (par.max_shrink_ratio / par.cur_font_step) / 2
- else
- shortfall = shortfall + total
- end
+ if l and getid(l) == glyph_code then
+ pw, lp = left_pw(l)
+ shortfall = shortfall + pw
end
end
- end
- local b = 0
- local g = 0
- local fit_class = fit_decent_class
- local found = false
- if shortfall > 0 then
- if cur_active_width.fi ~= 0 or cur_active_width.fil ~= 0 or cur_active_width.fill ~= 0 or cur_active_width.filll ~= 0 then
- if not do_last_line_fit then
- -- okay
- elseif not current then
- found, shortfall, fit_class, g, b = lastlinecrap(shortfall,r.active_short,r.active_glue,cur_active_width,par.fill_width,par.last_line_fit)
+ if checked_expansion and shortfall ~= 0 then
+ local margin_kern_stretch = 0
+ local margin_kern_shrink = 0
+ if protrude_chars > 1 then
+ if lp then
+ local char, font = isglyph(lp)
+ local data = expansions[font][char]
+ if data then
+ margin_kern_stretch, margin_kern_shrink = data.glyphstretch, data.glyphshrink
+ end
+ end
+ if rp then
+ local char, font = isglyph(rp)
+ local data = expansions[font][char]
+ if data then
+ margin_kern_stretch = margin_kern_stretch + data.glyphstretch
+ margin_kern_shrink = margin_kern_shrink + data.glyphshrink
+ end
+ end
+ end
+ local total = cur_active_width.adjust_stretch + margin_kern_stretch
+ if shortfall > 0 and total > 0 then
+ if total > shortfall then
+ shortfall = total / (par.max_stretch_ratio / par.cur_font_step) / 2
+ else
+ shortfall = shortfall - total
+ end
else
- shortfall = 0
+ total = cur_active_width.adjust_shrink + margin_kern_shrink
+ if shortfall < 0 and total > 0 then
+ if total > - shortfall then
+ shortfall = - total / (par.max_shrink_ratio / par.cur_font_step) / 2
+ else
+ shortfall = shortfall + total
+ end
+ end
end
- else
- local stretch = cur_active_width.stretch
- if shortfall > 7230584 and stretch < 1663497 then
- b = infinite_badness
- fit_class = fit_very_loose_class
+ end
+ local b = 0
+ local g = 0
+ local fit_class = fit_decent_class
+ local found = false
+ if shortfall > 0 then
+ if cur_active_width.fi ~= 0 or cur_active_width.fil ~= 0 or cur_active_width.fill ~= 0 or cur_active_width.filll ~= 0 then
+ if not do_last_line_fit then
+ -- okay
+ elseif not current then
+ found, shortfall, fit_class, g, b = lastlinecrap(shortfall,r.active_short,r.active_glue,cur_active_width,par.fill_width,par.last_line_fit)
+ else
+ shortfall = 0
+ end
else
- b = calculate_badness(shortfall,stretch)
- if b > 99 then
+ local stretch = cur_active_width.stretch
+ if shortfall > 7230584 and stretch < 1663497 then
+ b = infinite_badness
fit_class = fit_very_loose_class
- elseif b > 12 then
- fit_class = fit_loose_class
else
- fit_class = fit_decent_class
+ b = calculate_badness(shortfall,stretch)
+ if b > 99 then
+ fit_class = fit_very_loose_class
+ elseif b > 12 then
+ fit_class = fit_loose_class
+ else
+ fit_class = fit_decent_class
+ end
end
end
- end
- else
- local shrink = cur_active_width.shrink
- if -shortfall > shrink then
- b = infinite_badness + 1
- else
- b = calculate_badness(-shortfall,shrink)
- end
- if b > 12 then
- fit_class = fit_tight_class
- else
- fit_class = fit_decent_class
- end
- end
- if do_last_line_fit and not found then
- if not current then
- -- g = 0
- shortfall = 0
- elseif shortfall > 0 then
- g = cur_active_width.stretch
- elseif shortfall < 0 then
- g = cur_active_width.shrink
else
- g = 0
+ local shrink = cur_active_width.shrink
+ if -shortfall > shrink then
+ b = infinite_badness + 1
+ else
+ b = calculate_badness(-shortfall,shrink)
+ end
+ if b > 12 then
+ fit_class = fit_tight_class
+ else
+ fit_class = fit_decent_class
+ end
end
- end
- -- ::FOUND::
- local continue_only = false -- brrr
- if b > infinite_badness or pi == eject_penalty then
- if final_pass and par.minimum_demerits == awful_badness and r.next == par.active and prev_r == par.active then
- artificial_demerits = true -- set demerits zero, this break is forced
- node_r_stays_active = false
- elseif b > par.threshold then
- prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion)
- continue_only = true
- else
- node_r_stays_active = false
+ if do_last_line_fit and not found then
+ if not current then
+ -- g = 0
+ shortfall = 0
+ elseif shortfall > 0 then
+ g = cur_active_width.stretch
+ elseif shortfall < 0 then
+ g = cur_active_width.shrink
+ else
+ g = 0
+ end
end
- else
- prev_r = r
- if b > par.threshold then
- continue_only = true
+ -- ::FOUND::
+ local continue_only = false -- brrr
+ if b > infinite_badness or pi == eject_penalty then
+ if final_pass and par.minimum_demerits == awful_badness and r.next == par.active and prev_r == par.active then
+ artificial_demerits = true -- set demerits zero, this break is forced
+ node_r_stays_active = false
+ elseif b > par.threshold then
+ prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion)
+ continue_only = true
+ else
+ node_r_stays_active = false
+ end
else
- node_r_stays_active = true
- end
- end
- if not continue_only then
- local d = 0
- if not artificial_demerits then
- d = par.line_penalty + b
- if (d >= 0 and d or -d) >= 10000 then -- abs(d)
- d = 100000000
+ prev_r = r
+ if b > par.threshold then
+ continue_only = true
else
- d = d * d
+ node_r_stays_active = true
end
- if pi == 0 then
- -- nothing
- elseif pi > 0 then
- d = d + pi * pi
- elseif pi > eject_penalty then
- d = d - pi * pi
- end
- if break_type == hyphenated_code and r.id == hyphenated_code then
- if current then
- d = d + par.double_hyphen_demerits
+ end
+ if not continue_only then
+ local d = 0
+ if not artificial_demerits then
+ d = par.line_penalty + b
+ if (d >= 0 and d or -d) >= 10000 then -- abs(d)
+ d = 100000000
else
- d = d + par.final_hyphen_demerits
+ d = d * d
+ end
+ if pi == 0 then
+ -- nothing
+ elseif pi > 0 then
+ d = d + pi * pi
+ elseif pi > eject_penalty then
+ d = d - pi * pi
+ end
+ if break_type == hyphenated_code and r.id == hyphenated_code then
+ if current then
+ d = d + par.double_hyphen_demerits
+ else
+ d = d + par.final_hyphen_demerits
+ end
+ end
+ local delta = fit_class - r.subtype
+ if (delta >= 0 and delta or -delta) > 1 then -- abs(delta)
+ d = d + par.adj_demerits
end
end
- local delta = fit_class - r.subtype
- if (delta >= 0 and delta or -delta) > 1 then -- abs(delta)
- d = d + par.adj_demerits
+ if tracing_paragraphs then
+ diagnostics.feasible_break(par,current,r,b,pi,d,artificial_demerits)
end
- end
- if tracing_paragraphs then
- diagnostics.feasible_break(par,current,r,b,pi,d,artificial_demerits)
- end
- d = d + r.total_demerits -- this is the minimum total demerits from the beginning to current via r
- if d <= minimal_demerits[fit_class] then
- minimal_demerits[fit_class] = d
- best_place [fit_class] = r.break_node
- best_pl_line [fit_class] = line_number
- if do_last_line_fit then
- best_pl_short[fit_class] = shortfall
- best_pl_glue [fit_class] = g
- if trace_lastlinefit then
- report_parbuilders("storing last line fit short %a and glue %p in class %a",shortfall,g,fit_class)
+ d = d + r.total_demerits -- this is the minimum total demerits from the beginning to current via r
+ if d <= minimal_demerits[fit_class] then
+ minimal_demerits[fit_class] = d
+ best_place [fit_class] = r.break_node
+ best_pl_line [fit_class] = line_number
+ if do_last_line_fit then
+ best_pl_short[fit_class] = shortfall
+ best_pl_glue [fit_class] = g
+ if trace_lastlinefit then
+ report_parbuilders("storing last line fit short %a and glue %p in class %a",shortfall,g,fit_class)
+ end
+ end
+ if d < par.minimum_demerits then
+ par.minimum_demerits = d
end
end
- if d < par.minimum_demerits then
- par.minimum_demerits = d
+ if not node_r_stays_active then
+ prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion)
end
end
- if not node_r_stays_active then
- prev_r, r = deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion)
- end
end
end
end
-end
-
--- we can call the normal one for simple box building in the otr so we need
--- frequent enabling/disabling
-local dcolor = { [0] = "red", "green", "blue", "magenta", "cyan", "gray" }
+ -- we can call the normal one for simple box building in the otr so we need
+ -- frequent enabling/disabling
-local temp_head = new_temp()
+ local temp_head = new_temp()
-function constructors.methods.basic(head,d)
- head = tonut(head)
-
- if trace_basic then
- report_parbuilders("starting at %a",head)
- end
+ function constructors.methods.basic(head,d)
+ if trace_basic then
+ report_parbuilders("starting at %a",head)
+ end
- local par = initialize_line_break(head,d)
+ local par = initialize_line_break(head,d)
- local checked_expansion = par.checked_expansion
- local active_width = par.active_width
- local disc_width = par.disc_width
- local background = par.background
- local tracing_paragraphs = par.tracing_paragraphs
+ local checked_expansion = par.checked_expansion
+ local active_width = par.active_width
+ local disc_width = par.disc_width
+ local background = par.background
+ local tracing_paragraphs = par.tracing_paragraphs
- local dirstack = new_dir_stack()
+ local dirstack = new_dir_stack()
- if tracing_paragraphs then
- diagnostics.start()
- if par.pretolerance >= 0 then
- diagnostics.current_pass(par,"firstpass")
+ if tracing_paragraphs then
+ diagnostics.start()
+ if par.pretolerance >= 0 then
+ diagnostics.current_pass(par,"firstpass")
+ end
end
- end
- while true do
- reset_meta(par)
- if par.threshold > infinite_badness then
- par.threshold = infinite_badness
- end
- par.active.next = {
- id = unhyphenated_code,
- subtype = fit_decent_class,
- next = par.active,
- break_node = nil,
- line_number = par.first_line + 1,
- total_demerits = 0,
- active_short = 0,
- active_glue = 0,
- }
- active_width.size = background.size
- active_width.stretch = background.stretch
- active_width.fi = background.fi
- active_width.fil = background.fil
- active_width.fill = background.fill
- active_width.filll = background.filll
- active_width.shrink = background.shrink
-
- if checked_expansion then
- active_width.adjust_stretch = 0
- active_width.adjust_shrink = 0
- end
+ while true do
+ reset_meta(par)
+ if par.threshold > infinite_badness then
+ par.threshold = infinite_badness
+ end
+ par.active.next = {
+ id = unhyphenated_code,
+ subtype = fit_decent_class,
+ next = par.active,
+ break_node = nil,
+ line_number = par.first_line + 1,
+ total_demerits = 0,
+ active_short = 0,
+ active_glue = 0,
+ }
+ active_width.size = background.size
+ active_width.stretch = background.stretch
+ active_width.fi = background.fi
+ active_width.fil = background.fil
+ active_width.fill = background.fill
+ active_width.filll = background.filll
+ active_width.shrink = background.shrink
- par.passive = nil -- = 0
- par.printed_node = temp_head -- only when tracing, shared
- par.pass_number = 0
--- par.auto_breaking = true
+ if checked_expansion then
+ active_width.adjust_stretch = 0
+ active_width.adjust_shrink = 0
+ end
- setnext(temp_head,head)
+ par.passive = nil -- = 0
+ par.printed_node = temp_head -- only when tracing, shared
+ par.pass_number = 0
+ -- par.auto_breaking = true
- local current = head
- local first_p = current
+ setnext(temp_head,head)
- local auto_breaking = true
+ local current = head
+ local first_p = current
- par.font_in_short_display = 0
+ local auto_breaking = true
- if current then
- local id = getid(current)
- if id == localpar_code then
- par.init_internal_left_box = getfield(current,"box_left")
- par.init_internal_left_box_width = getfield(current,"box_left_width")
- par.internal_pen_inter = getfield(current,"pen_inter")
- par.internal_pen_broken = getfield(current,"pen_broken")
- par.internal_left_box = par.init_internal_left_box
- par.internal_left_box_width = par.init_internal_left_box_width
- par.internal_right_box = getfield(current,"box_right")
- par.internal_right_box_width = getfield(current,"box_right_width")
+ par.font_in_short_display = 0
+
+ if current then
+ local id = getid(current)
+ if id == localpar_code then
+ par.init_internal_left_box = getfield(current,"box_left")
+ par.init_internal_left_box_width = getfield(current,"box_left_width")
+ par.internal_pen_inter = getfield(current,"pen_inter")
+ par.internal_pen_broken = getfield(current,"pen_broken")
+ par.internal_left_box = par.init_internal_left_box
+ par.internal_left_box_width = par.init_internal_left_box_width
+ par.internal_right_box = getfield(current,"box_right")
+ par.internal_right_box_width = getfield(current,"box_right_width")
+ end
end
- end
- -- all passes are combined in this loop so maybe we should split this into
- -- three function calls; we then also need to do the wrap_up elsewhere
+ -- all passes are combined in this loop so maybe we should split this into
+ -- three function calls; we then also need to do the wrap_up elsewhere
- -- split into normal and expansion loop
+ -- split into normal and expansion loop
- -- use an active local
+ -- use an active local
- local fontexp, lastfont -- we can pass fontexp to calculate width if needed
+ local fontexp, lastfont -- we can pass fontexp to calculate width if needed
- -- i flattened the inner loop over glyphs .. it looks nicer and the extra p_active ~= n_active
- -- test is fast enough (and try_break now returns the updated values); the kern helper has been
- -- inlined as it did a double check on id so in fact we had hardly any code to share
+ -- i flattened the inner loop over glyphs .. it looks nicer and the extra p_active ~= n_active
+ -- test is fast enough (and try_break now returns the updated values); the kern helper has been
+ -- inlined as it did a double check on id so in fact we had hardly any code to share
- local p_active = par.active
- local n_active = p_active and p_active.next
- local second_pass = par.second_pass
+ local p_active = par.active
+ local n_active = p_active and p_active.next
+ local second_pass = par.second_pass
- trialcount = 0
+ trialcount = 0
- while current and p_active ~= n_active do
- local char, id = isglyph(current)
- if char then
- local wd, ht, dp = getwhd(current)
- if is_rotated[par.line_break_dir] then
- active_width.size = active_width.size + ht + dp
- else
- active_width.size = active_width.size + wd
- end
- if checked_expansion then
- local currentfont = getfont(current)
- local data = checked_expansion[currentfont]
- if data then
- if currentfont ~= lastfont then
- fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer
- lastfont = currentfont
- end
- if fontexps then
- local expansion = fontexps[char]
- if expansion then
- active_width.adjust_stretch = active_width.adjust_stretch + expansion.glyphstretch
- active_width.adjust_shrink = active_width.adjust_shrink + expansion.glyphshrink
+ while current and p_active ~= n_active do
+ local char, id = isglyph(current)
+ if char then
+ local wd, ht, dp = getwhd(current)
+ if is_rotated(par.line_break_dir) then
+ active_width.size = active_width.size + ht + dp
+ else
+ active_width.size = active_width.size + wd
+ end
+ if checked_expansion then
+ local font = id -- == font
+ local data = checked_expansion[font]
+ if data then
+ if font ~= lastfont then
+ fontexps = checked_expansion[font] -- a bit redundant for the par line packer
+ lastfont = currentfont
+ end
+ if fontexps then
+ local expansion = fontexps[char]
+ if expansion then
+ active_width.adjust_stretch = active_width.adjust_stretch + expansion.glyphstretch
+ active_width.adjust_shrink = active_width.adjust_shrink + expansion.glyphshrink
+ end
end
end
end
- end
- elseif id == hlist_code or id == vlist_code then
- local wd, ht, dp = getwhd(current)
- if is_parallel[getdir(current)][par.line_break_dir] then
- active_width.size = active_width.size + wd
- else
- active_width.size = active_width.size + ht + dp
- end
- elseif id == glue_code then
--- if par.auto_breaking then
- if auto_breaking then
- local prev_p = getprev(current)
- if prev_p and prev_p ~= temp_head then
- local id = getid(prev_p)
- -- we need to check this with the latest patches to the tex kernel
- if (id == glyph_code) or (id < math_code) then
- p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
- elseif id == kern_code then
- local s = getsubtype(prev_p)
- if s ~= userkern_code and s ~= italickern_code then
+ elseif id == hlist_code or id == vlist_code then
+ local wd, ht, dp = getwhd(current)
+ if textdir_parallel(getdirection(current),par.line_break_dir) then
+ active_width.size = active_width.size + wd
+ else
+ active_width.size = active_width.size + ht + dp
+ end
+ elseif id == glue_code then
+ -- if par.auto_breaking then
+ if auto_breaking then
+ local prev_p = getprev(current)
+ if prev_p and prev_p ~= temp_head then
+ local id = getid(prev_p)
+ -- we need to check this with the latest patches to the tex kernel
+ if (id == glyph_code) or (id < math_code) then
p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
+ elseif id == kern_code then
+ local s = getsubtype(prev_p)
+ if s ~= userkern_code and s ~= italickern_code then
+ p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
+ end
end
end
end
- end
- check_shrinkage(par,current)
- local width, stretch, shrink, stretch_order = getglue(current)
- local order = stretch_orders[stretch_order]
- active_width.size = active_width.size + width
- active_width[order] = active_width[order] + stretch
- active_width.shrink = active_width.shrink + shrink
- elseif id == disc_code then
- local subtype = getsubtype(current)
- if subtype ~= second_disc_code then
- local line_break_dir = par.line_break_dir
- if second_pass or subtype <= automatic_disc_code then
- local actual_pen = subtype == automatic_disc_code and par.ex_hyphen_penalty or par.hyphen_penalty
- -- 0.81 :
- -- local actual_pen = getpenalty(current)
- --
- local pre, post, replace = getdisc(current)
- if not pre then -- trivial pre-break
- disc_width.size = 0
- if checked_expansion then
- disc_width.adjust_stretch = 0
- disc_width.adjust_shrink = 0
- end
- p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion)
- else
- local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre)
- disc_width.size = size
- active_width.size = active_width.size + size
- if checked_expansion then
- disc_width.adjust_stretch = adjust_stretch
- disc_width.adjust_shrink = adjust_shrink
- active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch
- active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink
+ check_shrinkage(par,current)
+ local width, stretch, shrink, stretch_order = getglue(current)
+ local order = fillcodes[stretch_order]
+ active_width.size = active_width.size + width
+ active_width[order] = active_width[order] + stretch
+ active_width.shrink = active_width.shrink + shrink
+ elseif id == disc_code then
+ local subtype = getsubtype(current)
+ if subtype ~= seconddisc_code then
+ local line_break_dir = par.line_break_dir
+ if second_pass or subtype <= automaticdisc_code then
+ local actual_pen = subtype == automaticdisc_code and par.ex_hyphen_penalty or par.hyphen_penalty
+ -- 0.81 :
+ -- local actual_pen = getpenalty(current)
+ --
+ local pre, post, replace = getdisc(current)
+ if not pre then -- trivial pre-break
+ disc_width.size = 0
+ if checked_expansion then
+ disc_width.adjust_stretch = 0
+ disc_width.adjust_shrink = 0
+ end
+ p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion)
else
- -- disc_width.adjust_stretch = 0
- -- disc_width.adjust_shrink = 0
- end
- p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion)
- if subtype == first_disc_code then
- local cur_p_next = getnext(current)
- if getid(cur_p_next) ~= disc_code or getsubtype(cur_p_next) ~= second_disc_code then
- report_parbuilders("unsupported disc at location %a",1)
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre)
+ disc_width.size = size
+ active_width.size = active_width.size + size
+ if checked_expansion then
+ disc_width.adjust_stretch = adjust_stretch
+ disc_width.adjust_shrink = adjust_shrink
+ active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch
+ active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink
else
- local pre = getfield(cur_p_next,"pre")
- if pre then
- local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre)
- disc_width.size = disc_width.size + size
- if checked_expansion then
- disc_width.adjust_stretch = disc_width.adjust_stretch + adjust_stretch
- disc_width.adjust_shrink = disc_width.adjust_shrink + adjust_shrink
- end
- p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, cur_p_next, checked_expansion)
- --
- -- I will look into this some day ... comment in linebreak.w says that this fails,
- -- maybe this is what Taco means with his comment in the luatex manual.
- --
- -- do_one_seven_eight(sub_disc_width_from_active_width);
- -- do_one_seven_eight(reset_disc_width);
- -- s = vlink_no_break(vlink(current));
- -- add_to_widths(s, line_break_dir, adjust_spacing,disc_width);
- -- ext_try_break(...,first_p,vlink(current));
- --
+ -- disc_width.adjust_stretch = 0
+ -- disc_width.adjust_shrink = 0
+ end
+ p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion)
+ if subtype == firstdisc_code then
+ local cur_p_next = getnext(current)
+ if getid(cur_p_next) ~= disc_code or getsubtype(cur_p_next) ~= seconddisc_code then
+ report_parbuilders("unsupported disc at location %a",1)
else
- report_parbuilders("unsupported disc at location %a",2)
+ local pre = getfield(cur_p_next,"pre")
+ if pre then
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre)
+ disc_width.size = disc_width.size + size
+ if checked_expansion then
+ disc_width.adjust_stretch = disc_width.adjust_stretch + adjust_stretch
+ disc_width.adjust_shrink = disc_width.adjust_shrink + adjust_shrink
+ end
+ p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, cur_p_next, checked_expansion)
+ --
+ -- I will look into this some day ... comment in linebreak.w says that this fails,
+ -- maybe this is what Taco means with his comment in the luatex manual.
+ --
+ -- do_one_seven_eight(sub_disc_width_from_active_width);
+ -- do_one_seven_eight(reset_disc_width);
+ -- s = vlink_no_break(vlink(current));
+ -- add_to_widths(s, line_break_dir, adjust_spacing,disc_width);
+ -- ext_try_break(...,first_p,vlink(current));
+ --
+ else
+ report_parbuilders("unsupported disc at location %a",2)
+ end
end
end
+ -- beware, we cannot restore to a saved value as the try_break adapts active_width
+ active_width.size = active_width.size - disc_width.size
+ if checked_expansion then
+ active_width.adjust_stretch = active_width.adjust_stretch - disc_width.adjust_stretch
+ active_width.adjust_shrink = active_width.adjust_shrink - disc_width.adjust_shrink
+ end
end
- -- beware, we cannot restore to a saved value as the try_break adapts active_width
- active_width.size = active_width.size - disc_width.size
+ end
+ if replace then
+ local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace)
+ active_width.size = active_width.size + size
if checked_expansion then
- active_width.adjust_stretch = active_width.adjust_stretch - disc_width.adjust_stretch
- active_width.adjust_shrink = active_width.adjust_shrink - disc_width.adjust_shrink
+ active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch
+ active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink
end
end
end
- if replace then
- local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace)
- active_width.size = active_width.size + size
- if checked_expansion then
- active_width.adjust_stretch = active_width.adjust_stretch + adjust_stretch
- active_width.adjust_shrink = active_width.adjust_shrink + adjust_shrink
+ elseif id == kern_code then
+ local s = getsubtype(current)
+ if s == userkern_code or s == italickern_code then
+ local v = getnext(current)
+ -- if par.auto_breaking and getid(v) == glue_code then
+ if auto_breaking and getid(v) == glue_code then
+ p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
+ end
+ local active_width = par.active_width
+ active_width.size = active_width.size + getkern(current)
+ else
+ local kern = getkern(current)
+ if kern ~= 0 then
+ active_width.size = active_width.size + kern
+ if checked_expansion and expand_kerns and getsubtype(current) == fontkern_code then
+ local stretch, shrink = kern_stretch_shrink(current,kern)
+ if expand_kerns == "stretch" then
+ active_width.adjust_stretch = active_width.adjust_stretch + stretch
+ elseif expand_kerns == "shrink" then
+ active_width.adjust_shrink = active_width.adjust_shrink + shrink
+ else
+ active_width.adjust_stretch = active_width.adjust_stretch + stretch
+ active_width.adjust_shrink = active_width.adjust_shrink + shrink
+ end
+ end
end
end
- end
- elseif id == kern_code then
- local s = getsubtype(current)
- if s == userkern_code or s == italickern_code then
+ elseif id == math_code then
+ -- par.auto_breaking = getsubtype(current) == endmath_code
+ auto_breaking = getsubtype(current) == endmath_code
local v = getnext(current)
- -- if par.auto_breaking and getid(v) == glue_code then
+ -- if par.auto_breaking and getid(v) == glue_code then
if auto_breaking and getid(v) == glue_code then
p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
end
local active_width = par.active_width
- active_width.size = active_width.size + getkern(current)
- else
- local kern = getkern(current)
- if kern ~= 0 then
- active_width.size = active_width.size + kern
- if checked_expansion and expand_kerns and getsubtype(current) == fontkern_code then
- local stretch, shrink = kern_stretch_shrink(current,kern)
- if expand_kerns == "stretch" then
- active_width.adjust_stretch = active_width.adjust_stretch + stretch
- elseif expand_kerns == "shrink" then
- active_width.adjust_shrink = active_width.adjust_shrink + shrink
- else
- active_width.adjust_stretch = active_width.adjust_stretch + stretch
- active_width.adjust_shrink = active_width.adjust_shrink + shrink
- end
- end
+ active_width.size = active_width.size + getkern(current) -- surround
+ -- new in luatex
+ + getwidth(current)
+ elseif id == rule_code then
+ active_width.size = active_width.size + getwidth(current)
+ elseif id == penalty_code then
+ p_active, n_active = try_break(getpenalty(current), unhyphenated_code, par, first_p, current, checked_expansion)
+ elseif id == dir_code then
+ par.line_break_dir = checked_line_dir(dirstack) or par.line_break_dir
+ elseif id == localpar_code then
+ par.internal_pen_inter = getfield(current,"pen_inter")
+ par.internal_pen_broken = getfield(current,"pen_broken")
+ par.internal_left_box = getfield(current,"box_left")
+ par.internal_left_box_width = getfield(current,"box_left_width")
+ par.internal_right_box = getfield(current,"box_right")
+ par.internal_right_box_width = getfield(current,"box_right_width")
+ elseif trace_unsupported then
+ if id == mark_code or id == ins_code or id == adjust_code then
+ -- skip
+ else
+ report_parbuilders("node of type %a found in paragraph",type(id))
end
end
- elseif id == math_code then
--- par.auto_breaking = getsubtype(current) == endmath_code
- auto_breaking = getsubtype(current) == endmath_code
- local v = getnext(current)
--- if par.auto_breaking and getid(v) == glue_code then
- if auto_breaking and getid(v) == glue_code then
- p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion)
- end
- local active_width = par.active_width
- active_width.size = active_width.size + getkern(current) -- surround
- -- new in luatex
- + getwidth(current)
- elseif id == rule_code then
- active_width.size = active_width.size + getwidth(current)
- elseif id == penalty_code then
- p_active, n_active = try_break(getpenalty(current), unhyphenated_code, par, first_p, current, checked_expansion)
- elseif id == dir_code then
- par.line_break_dir = checked_line_dir(dirstack) or par.line_break_dir
- elseif id == localpar_code then
- par.internal_pen_inter = getfield(current,"pen_inter")
- par.internal_pen_broken = getfield(current,"pen_broken")
- par.internal_left_box = getfield(current,"box_left")
- par.internal_left_box_width = getfield(current,"box_left_width")
- par.internal_right_box = getfield(current,"box_right")
- par.internal_right_box_width = getfield(current,"box_right_width")
- elseif trace_unsupported then
- if id == mark_code or id == ins_code or id == adjust_code then
- -- skip
- else
- report_parbuilders("node of type %a found in paragraph",type(id))
- end
+ current = getnext(current)
end
- current = getnext(current)
- end
- if not current then
- local p_active, n_active = try_break(eject_penalty, hyphenated_code, par, first_p, current, checked_expansion)
- if n_active ~= p_active then
- local r = n_active
- par.fewest_demerits = awful_badness
- repeat -- use local d
- if r.id ~= delta_code and r.total_demerits < par.fewest_demerits then
- par.fewest_demerits = r.total_demerits
- par.best_bet = r
- end
- r = r.next
- until r == p_active
- par.best_line = par.best_bet.line_number
- local asked_looseness = par.looseness
- if asked_looseness == 0 then
- return tonode(wrap_up(par))
- end
- local r = n_active
- local actual_looseness = 0
- -- minimize assignments to par but happens seldom
- repeat
- if r.id ~= delta_code then
- local line_diff = r.line_number - par.best_line
- par.line_diff = line_diff
- if (line_diff < actual_looseness and asked_looseness <= line_diff) or
- (line_diff > actual_looseness and asked_looseness >= line_diff) then
- par.best_bet = r
- actual_looseness = line_diff
+ if not current then
+ local p_active, n_active = try_break(eject_penalty, hyphenated_code, par, first_p, current, checked_expansion)
+ if n_active ~= p_active then
+ local r = n_active
+ par.fewest_demerits = awful_badness
+ repeat -- use local d
+ if r.id ~= delta_code and r.total_demerits < par.fewest_demerits then
par.fewest_demerits = r.total_demerits
- elseif line_diff == actual_looseness and r.total_demerits < par.fewest_demerits then
par.best_bet = r
- par.fewest_demerits = r.total_demerits
end
+ r = r.next
+ until r == p_active
+ par.best_line = par.best_bet.line_number
+ local asked_looseness = par.looseness
+ if asked_looseness == 0 then
+ return wrap_up(par)
+ end
+ local r = n_active
+ local actual_looseness = 0
+ -- minimize assignments to par but happens seldom
+ repeat
+ if r.id ~= delta_code then
+ local line_diff = r.line_number - par.best_line
+ par.line_diff = line_diff
+ if (line_diff < actual_looseness and asked_looseness <= line_diff) or
+ (line_diff > actual_looseness and asked_looseness >= line_diff) then
+ par.best_bet = r
+ actual_looseness = line_diff
+ par.fewest_demerits = r.total_demerits
+ elseif line_diff == actual_looseness and r.total_demerits < par.fewest_demerits then
+ par.best_bet = r
+ par.fewest_demerits = r.total_demerits
+ end
+ end
+ r = r.next
+ until r == p_active
+ par.best_line = par.best_bet.line_number
+ if actual_looseness == asked_looseness or par.final_pass then
+ return wrap_up(par)
end
- r = r.next
- until r == p_active
- par.best_line = par.best_bet.line_number
- if actual_looseness == asked_looseness or par.final_pass then
- return tonode(wrap_up(par))
end
end
- end
- reset_meta(par) -- clean up the memory by removing the break nodes
- if not second_pass then
- if tracing_paragraphs then
- diagnostics.current_pass(par,"secondpass")
- end
- par.threshold = par.tolerance
- par.second_pass = true
- par.final_pass = par.emergency_stretch <= 0
- else
- if tracing_paragraphs then
- diagnostics.current_pass(par,"emergencypass")
+ reset_meta(par) -- clean up the memory by removing the break nodes
+ if not second_pass then
+ if tracing_paragraphs then
+ diagnostics.current_pass(par,"secondpass")
+ end
+ par.threshold = par.tolerance
+ par.second_pass = true
+ par.final_pass = par.emergency_stretch <= 0
+ else
+ if tracing_paragraphs then
+ diagnostics.current_pass(par,"emergencypass")
+ end
+ par.background.stretch = par.background.stretch + par.emergency_stretch
+ par.final_pass = true
end
- par.background.stretch = par.background.stretch + par.emergency_stretch
- par.final_pass = true
end
+ return wrap_up(par)
end
- return tonode(wrap_up(par))
+
end
-- standard tex logging .. will be adapted ..
@@ -2531,16 +2572,19 @@ do
while a do
local char, id = isglyph(a)
if char then
- local font = getfont(a)
- if font ~= font_in_short_display then
- write(target,tex.fontidentifier(font) .. ' ')
- font_in_short_display = font
+ -- id == font
+ if id ~= font_in_short_display then
+ write(target,tex.fontidentifier(id) .. ' ')
+ font_in_short_display = id
end
- -- todo: instead of components the split tounicode string
- if getsubtype(a) == ligature_code then
- font_in_short_display = short_display(target,getcomponents(a),font_in_short_display)
+ local u = chardata[id][char]
+ local u = u.unicode or char
+ if type(u) == "table" then
+ for i=1,#u do
+ write(target,utfchar(u[i]))
+ end
else
- write(target,utfchar(char))
+ write(target,utfchar(u))
end
elseif id == disc_code then
local pre, post, replace = getdisc(a)
@@ -2713,55 +2757,6 @@ do
local setnodecolor = nodes.tracers.colors.set
- local function glyph_width_height_depth(curdir,pdir,p)
- local wd, ht, dp = getwhd(p)
- if is_rotated[curdir] then
- if is_parallel[curdir][pdir] then
- local half = (ht + dp) / 2
- return wd, half, half
- else
- local half = wd / 2
- return ht + dp, half, half
- end
- elseif is_rotated[pdir] then
- if is_parallel[curdir][pdir] then
- local half = (ht + dp) / 2
- return wd, half, half
- else
- return ht + dp, wd, 0 -- weird
- end
- else
- if glyphdir_is_equal[curdir][pdir] then
- return wd, ht, dp
- elseif is_opposite[curdir][pdir] then
- return wd, dp, ht
- else -- can this happen?
- return ht + dp, wd, 0
- end
- end
- end
-
- local function pack_width_height_depth(curdir,pdir,p)
- local wd, ht, dp = getwhd(p)
- if is_rotated[curdir] then
- if is_parallel[curdir][pdir] then
- local half = (ht + dp) / 2
- return wd, half, half
- else -- can this happen?
- local half = wd / 2
- return ht + dp, half, half
- end
- else
- if pardir_is_equal[curdir][pdir] then
- return wd, ht, dp
- elseif is_opposite[curdir][pdir] then
- return wd, dp, ht
- else -- weird dimensions, can this happen?
- return ht + dp, wd, 0
- end
- end
- end
-
-- local function xpack(head,width,method,direction,analysis)
--
-- -- inspect(analysis)
@@ -2776,7 +2771,7 @@ do
-- local hlist = new_hlist()
--
-- setlist(hlist,head)
- -- setdir(hlist,direction or tex.textdir)
+ -- setdirection(hlist,direction or tex.textdirection)
-- setwhd(hlist,width,height,depth)
--
-- if delta == 0 then
@@ -2889,7 +2884,7 @@ do
local hlist = new_hlist()
- setdir(hlist,direction)
+ setdirection(hlist,direction)
if head == nil then
setwidth(hlist,width)
@@ -2942,10 +2937,10 @@ do
local char, id = isglyph(current)
if char then
if cal_expand_ratio then
- local currentfont = getfont(current)
- if currentfont ~= lastfont then
- fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer
- lastfont = currentfont
+ local font = id -- == font
+ if font ~= lastfont then
+ fontexps = checked_expansion[font] -- a bit redundant for the par line packer
+ lastfont = font
end
if fontexps then
local expansion = fontexps[char]
@@ -2958,7 +2953,7 @@ do
end
end
-- use inline
- local wd, ht, dp = glyph_width_height_depth(hpack_dir,"TLT",current) -- was TRT ?
+ local wd, ht, dp = getwhd(current)
natural = natural + wd
if ht > height then
height = ht
@@ -2984,7 +2979,7 @@ do
end
elseif id == disc_code then
local subtype = getsubtype(current)
- if subtype ~= second_disc_code then
+ if subtype ~= seconddisc_code then
-- todo : local stretch, shrink = char_stretch_shrink(s)
local replace = getfield(current,"replace")
if replace then
@@ -3008,7 +3003,7 @@ do
end
elseif id == hlist_code or id == vlist_code then
local sh = getshift(current)
- local wd, ht, dp = pack_width_height_depth(hpack_dir,getdir(current) or hpack_dir,current) -- added: or pack_dir
+ local wd, ht, dp = getwhd(current)
local hs, ds = ht - sh, dp + sh
natural = natural + wd
if hs > height then
@@ -3114,14 +3109,13 @@ do
local fontexps, lastfont
for i=1,expansion_index do
- local g = expansion_stack[i]
- local e = 0
- local char = isglyph(g)
+ local g = expansion_stack[i]
+ local e = 0
+ local char, font = isglyph(g)
if char then
- local currentfont = getfont(g)
- if currentfont ~= lastfont then
- fontexps = expansions[currentfont]
- lastfont = currentfont
+ if font ~= lastfont then
+ fontexps = expansions[font]
+ lastfont = font
end
local data = fontexps[char]
if trace_expansion then
@@ -3133,7 +3127,7 @@ do
local stretch, shrink = kern_stretch_shrink(g,kern)
e = font_expand_ratio * stretch / 1000
end
- setfield(g,"expansion_factor",e)
+ setexpansion(g,e)
end
end
local tso = total_stretch[order]
@@ -3171,14 +3165,13 @@ do
local fontexps, lastfont
for i=1,expansion_index do
- local g = expansion_stack[i]
- local e = 0
- local char = isglyph(g)
+ local g = expansion_stack[i]
+ local e = 0
+ local char, font = isglyph(g)
if char then
- local currentfont = getfont(g)
- if currentfont ~= lastfont then
- fontexps = expansions[currentfont]
- lastfont = currentfont
+ if font ~= lastfont then
+ fontexps = expansions[font]
+ lastfont = font
end
local data = fontexps[char]
if trace_expansion then
@@ -3190,7 +3183,7 @@ do
local stretch, shrink = kern_stretch_shrink(g,kern)
e = font_expand_ratio * shrink / 1000
end
- setfield(g,"expansion_factor",e)
+ setexpansion(g,e)
end
end
local tso = total_shrink[order]
@@ -3214,7 +3207,7 @@ do
local overfullrule = tex.overfullrule
if fuzz > hfuzz and overfullrule > 0 then
-- weird, is always called and no rules shows up
- setnext(slide_node_list(list),new_rule(overfullrule,nil,nil,getdir(hlist))) -- todo: find_tail
+ setnext(slide_node_list(list),new_rule(overfullrule,nil,nil,getdirection(hlist))) -- todo: find_tail
end
diagnostics.overfull_hbox(hlist,line,-delta)
end
diff --git a/tex/context/base/mkiv/node-met.lua b/tex/context/base/mkiv/node-met.lua
index 12a9256bc..f5db4babd 100644
--- a/tex/context/base/mkiv/node-met.lua
+++ b/tex/context/base/mkiv/node-met.lua
@@ -68,65 +68,70 @@ end
nodes = nodes or { }
local nodes = nodes
-local nodecodes = nodes.nodecodes
-
-nodes.tostring = node.tostring or tostring
-nodes.copy = node.copy
-nodes.copy_node = node.copy
-nodes.copy_list = node.copy_list
-nodes.delete = node.delete
-nodes.dimensions = node.dimensions
-nodes.rangedimensions = node.rangedimensions
-nodes.end_of_math = node.end_of_math
-nodes.flush = node.flush_node
-nodes.flush_node = node.flush_node
-nodes.flush_list = node.flush_list
-nodes.free = node.free
-nodes.insert_after = node.insert_after
-nodes.insert_before = node.insert_before
-nodes.hpack = node.hpack
-nodes.new = node.new
-nodes.tail = node.tail
-nodes.traverse = node.traverse
-nodes.traverse_id = node.traverse_id
-nodes.traverse_char = node.traverse_char
-nodes.slide = node.slide
-nodes.vpack = node.vpack
-nodes.fields = node.fields
-nodes.is_node = node.is_node
-nodes.setglue = node.setglue
-
-nodes.first_glyph = node.first_glyph
-nodes.has_glyph = node.has_glyph or node.first_glyph
-
-nodes.current_attr = node.current_attr
-nodes.has_field = node.has_field
-nodes.last_node = node.last_node
-nodes.usedlist = node.usedlist
-nodes.protrusion_skippable = node.protrusion_skippable
-nodes.check_discretionaries = node.check_discretionaries
-nodes.write = node.write
-
-nodes.count = node.count
-nodes.length = node.length
-
-nodes.has_attribute = node.has_attribute
-nodes.set_attribute = node.set_attribute
-nodes.find_attribute = node.find_attribute
-nodes.unset_attribute = node.unset_attribute
-
-nodes.protect_glyph = node.protect_glyph
-nodes.protect_glyphs = node.protect_glyphs
-nodes.unprotect_glyph = node.unprotect_glyph
-nodes.unprotect_glyphs = node.unprotect_glyphs
-nodes.kerning = node.kerning
-nodes.ligaturing = node.ligaturing
-nodes.mlist_to_hlist = node.mlist_to_hlist
-
-nodes.effective_glue = node.effective_glue
-nodes.getglue = node.getglue
-nodes.setglue = node.setglue
-nodes.is_zero_glue = node.is_zero_glue
+local nodecodes = nodes.nodecodes
+
+nodes.tostring = node.tostring or tostring
+nodes.copy = node.copy
+nodes.copy_node = node.copy
+nodes.copy_list = node.copy_list
+nodes.delete = node.delete
+nodes.dimensions = node.dimensions
+nodes.rangedimensions = node.rangedimensions
+nodes.end_of_math = node.end_of_math
+nodes.flush = node.flush_node
+nodes.flush_node = node.flush_node
+nodes.flush_list = node.flush_list
+nodes.free = node.free
+nodes.insert_after = node.insert_after
+nodes.insert_before = node.insert_before
+nodes.hpack = node.hpack
+nodes.new = node.new
+nodes.tail = node.tail
+nodes.traverse = node.traverse
+nodes.traverse_id = node.traverse_id
+nodes.traverse_char = node.traverse_char
+nodes.traverse_glyph = node.traverse_glyph
+nodes.traverse_list = node.traverse_list
+nodes.slide = node.slide
+nodes.vpack = node.vpack
+nodes.fields = node.fields
+nodes.is_node = node.is_node
+nodes.setglue = node.setglue
+nodes.uses_font = node.uses_font
+
+nodes.first_glyph = node.first_glyph
+nodes.has_glyph = node.has_glyph or node.first_glyph
+
+nodes.current_attr = node.current_attr
+nodes.has_field = node.has_field
+nodes.last_node = node.last_node
+nodes.usedlist = node.usedlist
+nodes.protrusion_skippable = node.protrusion_skippable
+nodes.check_discretionaries = node.check_discretionaries
+nodes.write = node.write
+nodes.flatten_discretionaries = node.flatten_discretionaries
+
+nodes.count = node.count
+nodes.length = node.length
+
+nodes.has_attribute = node.has_attribute
+nodes.set_attribute = node.set_attribute
+nodes.find_attribute = node.find_attribute
+nodes.unset_attribute = node.unset_attribute
+
+nodes.protect_glyph = node.protect_glyph
+nodes.protect_glyphs = node.protect_glyphs
+nodes.unprotect_glyph = node.unprotect_glyph
+nodes.unprotect_glyphs = node.unprotect_glyphs
+nodes.kerning = node.kerning
+nodes.ligaturing = node.ligaturing
+nodes.hyphenating = node.hyphenating
+nodes.mlist_to_hlist = node.mlist_to_hlist
+
+nodes.effective_glue = node.effective_glue
+nodes.getglue = node.getglue
+nodes.setglue = node.setglue
+nodes.is_zero_glue = node.is_zero_glue
nodes.tonode = function(n) return n end
nodes.tonut = function(n) return n end
@@ -163,7 +168,7 @@ local n_setlink = node.setlink or -- always
-- not that fast but not used often anyway
local h = nil
for i=1,select("#",...) do
- local n = (select(i,...))
+ local n = select(i,...)
if not n then
-- go on
elseif h then
@@ -621,7 +626,7 @@ local messyhack = table.tohash { -- temporary solution
nodecodes.action,
}
-table.setmetatableindex(keys,function(t,k)
+setmetatableindex(keys,function(t,k)
local v = (k == "attributelist" or k == nodecodes.attributelist) and { } or getfields(k)
if messyhack[k] then
for i=1,#v do
@@ -638,7 +643,7 @@ table.setmetatableindex(keys,function(t,k)
return v
end)
-table.setmetatableindex(whatsitkeys,function(t,k)
+setmetatableindex(whatsitkeys,function(t,k)
local v = getfields(whatsit_code,k)
if v[ 0] then v[#v+1] = "next" v[ 0] = nil end
if v[-1] then v[#v+1] = "prev" v[-1] = nil end
@@ -659,46 +664,3 @@ end
nodes.keys = keys -- [id][subtype]
nodes.fields = nodefields -- (n)
-
--- for the moment (pre 6380)
-
-if not nodes.unprotect_glyph then
-
- local protect_glyph = nodes.protect_glyph
- local protect_glyphs = nodes.protect_glyphs
- local unprotect_glyph = nodes.unprotect_glyph
- local unprotect_glyphs = nodes.unprotect_glyphs
-
- local getnext = nodes.getnext
- local setnext = nodes.setnext
-
- function nodes.protectglyphs(first,last)
- if first == last then
- return protect_glyph(first)
- elseif last then
- local nxt = getnext(last)
- setnext(last)
- local f, b = protect_glyphs(first)
- setnext(last,nxt)
- return f, b
- else
- return protect_glyphs(first)
- end
- end
-
- function nodes.unprotectglyphs(first,last)
- if first == last then
- return unprotect_glyph(first)
- elseif last then
- local nxt = getnext(last)
- setnext(last)
- local f, b = unprotect_glyphs(first)
- setnext(last,nxt)
- return f, b
- else
- return unprotect_glyphs(first)
- end
- end
-
-end
-
diff --git a/tex/context/base/mkiv/node-mig.lua b/tex/context/base/mkiv/node-mig.lua
index b3820a7d8..32b09a186 100644
--- a/tex/context/base/mkiv/node-mig.lua
+++ b/tex/context/base/mkiv/node-mig.lua
@@ -89,12 +89,11 @@ local function locate(head,first,last,ni,nm)
end
function nodes.handlers.migrate(head,where)
- local done = false
if head then
if trace_migrations then
report_nodes("migration sweep %a",where)
end
- local current = tonut(head)
+ local current = head
while current do
local id = getid(current)
-- inserts_too is a temp hack, we should only do them when it concerns
@@ -124,13 +123,12 @@ function nodes.handlers.migrate(head,where)
setlink(last,n)
end
setlink(current,first)
- done = true
current = last
end
end
current = getnext(next)
end
- return head, done
+ return head
end
end
diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua
index 3e9a08b48..6a38cca67 100644
--- a/tex/context/base/mkiv/node-nut.lua
+++ b/tex/context/base/mkiv/node-nut.lua
@@ -96,6 +96,7 @@ local fastcopy = table.fastcopy
local nodecodes = nodes.nodecodes
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
+local glyph_code = nodecodes.glyph
local nuts = nodes.nuts or { }
nodes.nuts = nuts
@@ -126,11 +127,11 @@ nodes.tonut = tonut
-- function nuts.reportattr()
-- inspect(hash)
-- end
---
+
-- local function track(name)
-- local n = 0
--- local f = nuts[name]
--- function nuts[name](...)
+-- local f = direct[name]
+-- direct[name] = function(...)
-- n = n + 1
-- if n % 1000 == 0 then
-- print(name,n)
@@ -138,112 +139,81 @@ nodes.tonut = tonut
-- return f(...)
-- end
-- end
---
-- track("getfield")
-- helpers
-if not direct.getfam then -- LUATEXVERSION < 1.070
-
- local getfield = direct.getfield
- local setfield = direct.setfield
-
- direct.getfam = function(n) return getfield(n,"small_fam") end
- direct.setfam = function(n,f) setfield(n,"small_fam",f) end
-
-end
-
-if not direct.getdirection then
-
- local getdir = direct.getdir
- local setdir = direct.setdir
-
- direct.getdirection = function(n)
- local d = getdir(n)
- if d == "TLT" then return 0 end
- if d == "+TLT" then return 0, false end
- if d == "-TLT" then return 0, true end
- if d == "TRT" then return 1 end
- if d == "+TRT" then return 1, false end
- if d == "-TRT" then return 1, true end
- if d == "LTL" then return 2 end
- if d == "+LTL" then return 2, false end
- if d == "-LTL" then return 2, true end
- if d == "RTT" then return 3 end
- if d == "+RTT" then return 3, false end
- if d == "-RTT" then return 3, true end
- end
-
- direct.setdirection = function(n,d,c)
- if d == 0 then if c == true then setdir(n,"-TLT") elseif c == false then setdir(n,"+TLT") else setdir(n,"TLT") end
- elseif d == 1 then if c == true then setdir(n,"-TRT") elseif c == false then setdir(n,"+TRT") else setdir(n,"TRT") end
- elseif d == 2 then if c == true then setdir(n,"-LTL") elseif c == false then setdir(n,"+LTL") else setdir(n,"LTL") end
- elseif d == 3 then if c == true then setdir(n,"-RTT") elseif c == false then setdir(n,"+RTT") else setdir(n,"RTT") end
- else if c == true then setdir(n,"-TLT") elseif c == false then setdir(n,"+TLT") else setdir(n,"TLT") end end
- end
-
-end
-
-local nuts = nodes.nuts
-
-nuts.tostring = direct.tostring
-nuts.copy = direct.copy
-nuts.copy_node = direct.copy
-nuts.copy_list = direct.copy_list
-nuts.delete = direct.delete
-nuts.dimensions = direct.dimensions
-nuts.rangedimensions = direct.rangedimensions
-nuts.end_of_math = direct.end_of_math
-nuts.flush = direct.flush_node
-nuts.flush_node = direct.flush_node
-nuts.flush_list = direct.flush_list
-nuts.free = direct.free
-nuts.insert_after = direct.insert_after
-nuts.insert_before = direct.insert_before
-nuts.hpack = direct.hpack
-nuts.new = direct.new
-nuts.tail = direct.tail
-nuts.traverse = direct.traverse
-nuts.traverse_id = direct.traverse_id
-nuts.traverse_char = direct.traverse_char
-nuts.slide = direct.slide
-nuts.writable_spec = direct.writable_spec
-nuts.vpack = direct.vpack
-nuts.is_node = direct.is_node
-nuts.is_direct = direct.is_direct
-nuts.is_nut = direct.is_direct
-nuts.first_glyph = direct.first_glyph
-nuts.has_glyph = direct.has_glyph or direct.first_glyph
-nuts.count = direct.count
-nuts.length = direct.length
-nuts.find_attribute = direct.find_attribute
-nuts.unset_attribute = direct.unset_attribute
-
-nuts.current_attr = direct.current_attr
-nuts.has_field = direct.has_field
-nuts.last_node = direct.last_node
-nuts.usedlist = direct.usedlist
-nuts.protrusion_skippable = direct.protrusion_skippable
-nuts.check_discretionaries = direct.check_discretionaries
-nuts.write = direct.write
-
-nuts.has_attribute = direct.has_attribute
-nuts.set_attribute = direct.set_attribute
-nuts.unset_attribute = direct.unset_attribute
-
-nuts.protect_glyph = direct.protect_glyph
-nuts.protect_glyphs = direct.protect_glyphs
-nuts.unprotect_glyph = direct.unprotect_glyph
-nuts.unprotect_glyphs = direct.unprotect_glyphs
-nuts.ligaturing = direct.ligaturing
-nuts.kerning = direct.kerning
-
-if not direct.mlist_to_hlist then -- needed
+local nuts = nodes.nuts
+
+nuts.check_discretionaries = direct.check_discretionaries
+nuts.copy = direct.copy
+nuts.copy_list = direct.copy_list
+nuts.copy_node = direct.copy
+nuts.count = direct.count
+nuts.current_attr = direct.current_attr
+nuts.delete = direct.delete
+nuts.dimensions = direct.dimensions
+nuts.end_of_math = direct.end_of_math
+nuts.find_attribute = direct.find_attribute
+nuts.first_glyph = direct.first_glyph
+nuts.flatten_discretionaries = direct.flatten_discretionaries
+nuts.flush = direct.flush_node
+nuts.flush_list = direct.flush_list
+nuts.flush_node = direct.flush_node
+nuts.free = direct.free
+nuts.get_synctex_fields = direct.get_synctex_fields
+nuts.has_attribute = direct.has_attribute
+nuts.has_field = direct.has_field
+nuts.has_glyph = direct.has_glyph or direct.first_glyph
+nuts.hpack = direct.hpack
+nuts.insert_after = direct.insert_after
+nuts.insert_before = direct.insert_before
+nuts.is_direct = direct.is_direct
+nuts.is_node = direct.is_node
+nuts.is_nut = direct.is_direct
+nuts.kerning = direct.kerning
+nuts.hyphenating = direct.hyphenating
+nuts.last_node = direct.last_node
+nuts.length = direct.length
+nuts.ligaturing = direct.ligaturing
+nuts.new = direct.new
+nuts.protect_glyph = direct.protect_glyph
+nuts.protect_glyphs = direct.protect_glyphs
+nuts.flush_components = direct.flush_components
+nuts.protrusion_skippable = direct.protrusion_skippable
+nuts.rangedimensions = direct.rangedimensions
+nuts.set_attribute = direct.set_attribute
+nuts.set_synctex_fields = direct.set_synctex_fields
+nuts.slide = direct.slide
+nuts.tail = direct.tail
+nuts.tostring = direct.tostring
+nuts.traverse = direct.traverse
+nuts.traverse_char = direct.traverse_char
+nuts.traverse_glyph = direct.traverse_glyph
+nuts.traverse_id = direct.traverse_id
+nuts.traverse_list = direct.traverse_list
+nuts.unprotect_glyph = direct.unprotect_glyph
+nuts.unprotect_glyphs = direct.unprotect_glyphs
+nuts.unset_attribute = direct.unset_attribute
+nuts.unset_attribute = direct.unset_attribute
+nuts.usedlist = direct.usedlist
+nuts.uses_font = direct.uses_font
+nuts.vpack = direct.vpack
+nuts.writable_spec = direct.writable_spec
+nuts.write = direct.write
+nuts.mlist_to_hlist = direct.mlist_to_hlist
+
+if not nuts.mlist_to_hlist then
local n_mlist_to_hlist = node.mlist_to_hlist
- function nuts.mlist_to_hlist(head)
- return tonode(n_mlist_to_hlist(tonut(head)))
+ function nuts.mlist_to_hlist(head,...)
+ if head then
+ local head = n_mlist_to_hlist(tonode(head),...)
+ if head then
+ return tonut(head)
+ end
+ end
end
end
@@ -276,6 +246,14 @@ nuts.setdisc = direct.setdisc
nuts.getdiscretionary = direct.getdisc
nuts.setdiscretionary = direct.setdisc
+nuts.getdata = direct.getdata
+nuts.setdata = direct.setdata
+nuts.getvalue = direct.getdata
+nuts.setvalue = direct.setdata
+
+nuts.getexpansion = direct.getexpansion
+nuts.setexpansion = direct.setexpansion
+
nuts.getwhd = direct.getwhd
nuts.setwhd = direct.setwhd
nuts.getwidth = direct.getwidth
@@ -286,6 +264,8 @@ nuts.getdepth = direct.getdepth
nuts.setdepth = direct.setdepth
nuts.getshift = direct.getshift
nuts.setshift = direct.setshift
+nuts.getorientation = direct.getorientation or function() end
+nuts.setorientation = direct.setorientation or function() end
nuts.getnucleus = direct.getnucleus
nuts.setnucleus = direct.setnucleus
@@ -726,14 +706,10 @@ nodes.properties = {
data = propertydata,
}
-------.set_properties_mode(true,false) -- shallow copy ... problem: in fonts we then affect the originals too
-direct.set_properties_mode(true,true) -- create metatable, slower but needed for font-otj.lua (unless we use an intermediate table)
-
--- todo:
---
--- function direct.set_properties_mode()
--- -- we really need the set modes
--- end
+if direct.set_properties_mode then
+ direct.set_properties_mode(true,true) -- create metatable, slower but needed for font-otj.lua (unless we use an intermediate table)
+ function direct.set_properties_mode() end
+end
-- experimental code with respect to copying attributes has been removed
-- as it doesn't pay of (most attributes are only accessed once anyway)
@@ -770,8 +746,22 @@ nuts.theprop = function(n)
return p
end
-nodes.setprop = nodes.setproperty
-nodes.getprop = nodes.getproperty
+nuts.isdone = function(n,k)
+ local p = propertydata[n]
+ if not p then
+ propertydata[n] = { [k] = true }
+ return false
+ end
+ local v = p[k]
+ if v == nil then
+ propertydata[n] = { [k] = true }
+ return false
+ end
+ return v
+end
+
+-- nodes.setprop = nodes.setproperty
+-- nodes.getprop = nodes.getproperty
function nuts.copy_properties(source,target,what)
local newprops = propertydata[source]
@@ -800,116 +790,3 @@ function nuts.copy_properties(source,target,what)
end
return newprops -- for checking
end
-
--- here:
-
-nuts.get_synctex_fields = direct.get_synctex_fields
-nuts.set_synctex_fields = direct.set_synctex_fields
-
--- for now
-
-nodes.uses_font = nodes.uses_font
-nuts.uses_font = direct.uses_font
-
-if not nuts.uses_font then
-
- local glyph_code = nodecodes.glyph
- local getdisc = nuts.getdisc
- local getfont = nuts.getfont
- local traverse_id = nuts.traverse_id
- local tonut = nodes.tonut
-
- function nuts.uses_font(n,font)
- local pre, post, replace = getdisc(n)
- if pre then
- -- traverse_char
- for n in traverse_id(glyph_code,pre) do
- if getfont(n) == font then
- return true
- end
- end
- end
- if post then
- for n in traverse_id(glyph_code,post) do
- if getfont(n) == font then
- return true
- end
- end
- end
- if replace then
- for n in traverse_id(glyph_code,replace) do
- if getfont(n) == font then
- return true
- end
- end
- end
- return false
- end
-
- function nodes.uses_font(n,font)
- return nuts.uses_font(tonut(n),font)
- end
-
-end
-
--- for the moment (pre 6380)
-
-if not nuts.unprotect_glyph then
-
- local protect_glyph = nuts.protect_glyph
- local protect_glyphs = nuts.protect_glyphs
- local unprotect_glyph = nuts.unprotect_glyph
- local unprotect_glyphs = nuts.unprotect_glyphs
-
- local getnext = nuts.getnext
- local setnext = nuts.setnext
-
- function nuts.protectglyphs(first,last)
- if first == last then
- return protect_glyph(first)
- elseif last then
- local nxt = getnext(last)
- setnext(last)
- local f, b = protect_glyphs(first)
- setnext(last,nxt)
- return f, b
- else
- return protect_glyphs(first)
- end
- end
-
- function nuts.unprotectglyphs(first,last)
- if first == last then
- return unprotect_glyph(first)
- elseif last then
- local nxt = getnext(last)
- setnext(last)
- local f, b = unprotect_glyphs(first)
- setnext(last,nxt)
- return f, b
- else
- return unprotect_glyphs(first)
- end
- end
-
-end
-
-if LUATEXFUNCTIONALITY < 6384 then -- LUATEXVERSION < 1.070
-
- local getfield = nuts.getfield
- local setfield = nuts.setfield
-
- function nuts.getboxglue(n,glue_set,glue_order,glue_sign)
- return
- getfield(n,"glue_set"),
- getfield(n,"glue_order"),
- getfield(n,"glue_sign")
- end
-
- function nuts.setboxglue(n,glue_set,glue_order,glue_sign)
- setfield(n,"glue_set", glue_set or 0)
- setfield(n,"glue_order",glue_order or 0)
- setfield(n,"glue_sign", glue_sign or 0)
- end
-
-end
diff --git a/tex/context/base/mkiv/node-par.lua b/tex/context/base/mkiv/node-par.lua
new file mode 100644
index 000000000..8564c8764
--- /dev/null
+++ b/tex/context/base/mkiv/node-par.lua
@@ -0,0 +1,48 @@
+if not modules then modules = { } end modules ['node-par'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+
+local sequencers = utilities.sequencers
+
+-- This are called a lot!
+
+local actions = nodes.tasks.actions("everypar")
+
+local function everypar(head)
+ starttiming(builders)
+ head = actions(head)
+ stoptiming(builders)
+ return head
+end
+
+callbacks.register("insert_local_par",everypar,"after paragraph start")
+
+local actions = sequencers.new {
+ name = "newgraf",
+ arguments = "mode,indented",
+ returnvalues = "indented",
+ results = "indented",
+}
+
+sequencers.appendgroup(actions,"before") -- user
+sequencers.appendgroup(actions,"system") -- private
+sequencers.appendgroup(actions,"after" ) -- user
+
+local function newgraf(mode,indented)
+ local runner = actions.runner
+ if runner then
+ starttiming(builders)
+ indent = runner(mode,indented)
+ stoptiming(builders)
+ end
+ return indented
+end
+
+callbacks.register("new_graf",newgraf,"before paragraph start")
diff --git a/tex/context/base/mkiv/node-ppt.lua b/tex/context/base/mkiv/node-ppt.lua
index 5ebfca87d..485e742b6 100644
--- a/tex/context/base/mkiv/node-ppt.lua
+++ b/tex/context/base/mkiv/node-ppt.lua
@@ -26,12 +26,14 @@ local getid = nuts.getid
local getnext = nuts.getnext
local getprev = nuts.getprev
local getsubtype = nuts.getsubtype
-local getfield = nuts.getfield
local getlist = nuts.getlist
local setlist = nuts.setlist
+local getprop = nuts.getprop
+
local removenode = nuts.remove
-local traverse = nuts.traverse
-local traverse_id = nuts.traverse_id
+
+local nextnode = nuts.traversers.node
+local nextwhatsit = nuts.traversers.whatsit
local nodecodes = nodes.nodecodes
local whatsitcodes = nodes.whatsitcodes
@@ -39,18 +41,17 @@ local whatsitcodes = nodes.whatsitcodes
local whatsit_code = nodecodes.whatsit
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
-local userdefined_code = whatsitcodes.userdefined
+
+local userdefinedwhatsit_code = whatsitcodes.userdefined
local nodepool = nodes.pool
-local new_usernumber = nodepool.usernumber
+local new_usernode = nodepool.usernode
local variables = interfaces.variables
local v_before = variables.before
local v_after = variables.after
local v_here = variables.here
-local cache = { }
-local nofslots = 0
local property_id = nodepool.userids["property"]
local properties = nodes.properties
@@ -71,15 +72,8 @@ local function register(where,data,...)
where = v_after
end
if data then
- local data = { where, data, ... }
nofslots = nofslots + 1
- if nofslots > 1 then
- cache[nofslots] = data
- else
- -- report("restarting attacher")
- cache = { data } -- also forces collection
- end
- return new_usernumber(property_id,nofslots)
+ return new_usernode(property_id,{ where, data, ... })
end
end
@@ -108,17 +102,9 @@ local f_delayed = formatters["return function(target,head,where,propdata,paren
local f_immediate = formatters["return function(target,head,where,propdata) %s end"]
local nofdelayed = 0 -- better is to keep track of it per page ... we can have deleted nodes with properties
+local nofslots = 0
function actions.delayed(target,head,where,propdata,code,...) -- this one is used at the tex end
--- local kind = type(code)
--- if kind == "string" then
--- code, err = load(f_delayed(code))
--- if code then
--- code = code()
--- end
--- elseif kind ~= "function" then
--- code = nil
--- end
if code then
local delayed = propdata.delayed
if delayed then
@@ -131,15 +117,6 @@ function actions.delayed(target,head,where,propdata,code,...) -- this one is use
end
function actions.fdelayed(target,head,where,propdata,code,...) -- this one is used at the tex end
--- local kind = type(code)
--- if kind == "string" then
--- code, err = load(f_delayed(code))
--- if code then
--- code = code()
--- end
--- elseif kind ~= "function" then
--- code = nil
--- end
if code then
local delayed = propdata.delayed
if delayed then
@@ -170,81 +147,41 @@ function actions.immediate(target,head,where,propdata,code,...) -- this one is u
end
end
--- another experiment (a table or function closure are equally efficient); a function
--- is easier when we want to experiment with different (compatible) implementations
-
--- local nutpool = nuts.pool
--- local nut_usernumber = nutpool.usernumber
-
--- function nodes.nuts.pool.deferredfunction(...)
--- nofdelayed = nofdelayed + 1
--- local n = nut_usernumber(property_id,0)
--- propertydata[n] = { deferred = { ... } }
--- return n
--- end
-
--- function nodes.nuts.pool.deferredfunction(f)
--- nofdelayed = nofdelayed + 1
--- local n = nut_usernumber(property_id,0)
--- propertydata[n] = { deferred = f }
--- return n
--- end
-
--- maybe actions will get parent too
-
local function delayed(head,parent) -- direct based
- for target in traverse(head) do
+ for target, id in nextnode, head do
local p = propertydata[target]
if p then
- -- local deferred = p.deferred -- kind of late lua (but too soon as we have no access to pdf.h/v)
- -- if deferred then
- -- -- if #deferred > 0 then
- -- -- deferred[1](unpack(deferred,2))
- -- -- else
- -- -- deferred[1]()
- -- -- end
- -- deferred()
- -- p.deferred = false
- -- if nofdelayed == 1 then
- -- nofdelayed = 0
- -- return head
- -- else
- -- nofdelayed = nofdelayed - 1
- -- end
- -- else
- local delayed = p.delayed
- if delayed then
- for i=1,#delayed do
- local d = delayed[i]
- local code = d[2]
- local kind = type(code)
- if kind == "string" then
- code, err = load(f_delayed(code))
- if code then
- code = code()
- end
- end
- local where = d[1]
- if where then
- local h = code(target,where,head,p,parent,unpack(d,3)) -- target where propdata head parent
- if h and h ~= head then
- head = h
- end
- else
- code(unpack(d,3))
+ local delayed = p.delayed
+ if delayed then
+ for i=1,#delayed do
+ local d = delayed[i]
+ local code = d[2]
+ local kind = type(code)
+ if kind == "string" then
+ code, err = load(f_delayed(code))
+ if code then
+ code = code()
end
end
- p.delayed = nil
- if nofdelayed == 1 then
- nofdelayed = 0
- return head
+ local where = d[1]
+ if where then
+ local h = code(target,where,head,p,parent,unpack(d,3)) -- target where propdata head parent
+ if h and h ~= head then
+ head = h
+ end
else
- nofdelayed = nofdelayed - 1
+ code(unpack(d,3))
end
end
- -- end
+ p.delayed = nil
+ if nofdelayed == 1 then
+ nofdelayed = 0
+ return head
+ else
+ nofdelayed = nofdelayed - 1
+ end
+ end
end
- local id = getid(target)
if id == hlist_code or id == vlist_code then
local list = getlist(target)
if list then
@@ -268,14 +205,13 @@ function properties.delayed(head) --
if nofdelayed > 0 then
-- if next(propertydata) then
starttiming(properties)
- head = delayed(tonut(head))
+ head = delayed(head)
stoptiming(properties)
- return tonode(head), true -- done in shipout anyway
-- else
-- delayed = 0
- -- end
+ -- end
end
- return head, false
+ return head
end
-- more explicit ones too
@@ -284,7 +220,7 @@ local anchored = {
[v_before] = function(n)
while n do
n = getprev(n)
- if getid(n) == whatsit_code and getsubtype(n) == user_code and getfield(n,"user_id") == property_id then
+ if getid(n) == whatsit_code and getsubtype(n) == user_code and getprop(n,"id") == property_id then
-- continue
else
return n
@@ -296,7 +232,7 @@ local anchored = {
n = getnext(n)
if getid(n) == whatsit_code then
local subtype = getsubtype(n)
- if (subtype == userdefined_code and getfield(n,"user_id") == property_id) then
+ if (subtype == userdefinedwhatsit_code and getprop(n,"id") == property_id) then
-- continue
else
return n
@@ -320,26 +256,22 @@ end)
function properties.attach(head)
if nofslots <= 0 then
- return head, false
+ return head
end
- local done = false
local last = nil
- local head = tonut(head)
starttiming(properties)
- for source in traverse_id(whatsit_code,head) do
- if getsubtype(source) == userdefined_code then
+ for source, subtype in nextwhatsit, head do
+ if subtype == userdefinedwhatsit_code then
if last then
removenode(head,last,true)
last = nil
end
- if getfield(source,"user_id") == property_id then
- local slot = getfield(source,"value")
- local data = cache[slot]
+ if getprop(source,"id") == property_id then
+ local data = getprop(source,"data")
if data then
- cache[slot] = nil
local where = data[1]
local target = anchored[where](source)
if target then
@@ -393,7 +325,7 @@ function properties.attach(head)
target,nodecodes[getid(target)],serialize(propertydata[target],false))
end
end
- if nofslots == 1 then
+ if nofslots == 1 then
nofslots = 0
last = source
break
@@ -412,25 +344,22 @@ function properties.attach(head)
stoptiming(properties)
- return head, done
+ return head
end
-local tasks = nodes.tasks
-
-- maybe better hard coded in-place
--- tasks.prependaction("processors","before","nodes.properties.attach")
--- tasks.appendaction("shipouts","normalizers","nodes.properties.delayed")
-
statistics.register("properties processing time", function()
return statistics.elapsedseconds(properties)
end)
-- only for development
+-- local tasks = nodes.tasks
+--
-- local function show(head,level,report)
--- for target in traverse(head) do
+-- for target in nextnode, head do
-- local p = propertydata[target]
-- if p then
-- report("level %i, node %i, id %s, data %s",
diff --git a/tex/context/base/mkiv/node-pro.lua b/tex/context/base/mkiv/node-pro.lua
index 4509bac18..b6b130588 100644
--- a/tex/context/base/mkiv/node-pro.lua
+++ b/tex/context/base/mkiv/node-pro.lua
@@ -35,7 +35,7 @@ do
local n = 0
local function reconstruct(head) -- we probably have a better one
- local t, n, h = { }, 0, tonut(head)
+ local t, n, h = { }, 0, head
while h do
n = n + 1
local char, id = isglyph(h)
@@ -49,7 +49,7 @@ do
return concat(t)
end
- function processors.tracer(what,state,head,groupcode,before,after,show)
+ function processors.tracer(what,head,groupcode,before,after,show)
if not groupcode then
groupcode = "unknown"
elseif groupcode == "" then
@@ -57,16 +57,14 @@ do
end
n = n + 1
if show then
- report_nodes("%s: location %a, state %a, group %a, # before %a, # after %s, stream: %s",what,n,state,groupcode,before,after,reconstruct(head))
+ report_nodes("%s: location %a, group %a, # before %a, # after %s, stream: %s",what,n,groupcode,before,after,reconstruct(head))
else
- report_nodes("%s: location %a, state %a, group %a, # before %a, # after %s",what,n,state,groupcode,before,after)
+ report_nodes("%s: location %a, group %a, # before %a, # after %s",what,n,groupcode,before,after)
end
end
end
-local tracer = processors.tracer
-
processors.enabled = true -- this will become a proper state (like trackers)
do
@@ -74,154 +72,131 @@ do
local has_glyph = nodes.has_glyph
local count_nodes = nodes.countall
- function processors.pre_linebreak_filter(head,groupcode) -- ,size,packtype,direction
+ local texget = tex.get
+
+ local tracer = processors.tracer
+
+ local function pre_linebreak_filter(head,groupcode)
local found = force_processors or has_glyph(head)
if found then
if trace_callbacks then
local before = count_nodes(head,true)
- local head, done = actions(head,groupcode) -- ,size,packtype,direction
+ head = actions(head,groupcode)
local after = count_nodes(head,true)
- if done then
- tracer("pre_linebreak","changed",head,groupcode,before,after,true)
- else
- tracer("pre_linebreak","unchanged",head,groupcode,before,after,true)
- end
- return done and head or true
+ tracer("pre_linebreak",head,groupcode,before,after,true)
else
- local head, done = actions(head,groupcode) -- ,size,packtype,direction
- return done and head or true
+ head = actions(head,groupcode)
end
elseif trace_callbacks then
local n = count_nodes(head,false)
- tracer("pre_linebreak","no chars",head,groupcode,n,n)
+ tracer("pre_linebreak",head,groupcode,n,n)
end
- return true
+ return head
end
local function hpack_filter(head,groupcode,size,packtype,direction,attributes)
local found = force_processors or has_glyph(head)
if found then
+ --
+ -- yes or no or maybe an option
+ --
+ if not direction then
+ direction = texget("textdir")
+ end
+ --
if trace_callbacks then
local before = count_nodes(head,true)
- local head, done = actions(head,groupcode,size,packtype,direction,attributes)
+ head = actions(head,groupcode,size,packtype,direction,attributes)
local after = count_nodes(head,true)
- if done then
- tracer("hpack","changed",head,groupcode,before,after,true)
- else
- tracer("hpack","unchanged",head,groupcode,before,after,true)
- end
- return done and head or true
+ tracer("hpack",head,groupcode,before,after,true)
else
- local head, done = actions(head,groupcode,size,packtype,direction,attributes)
- return done and head or true
+ head = actions(head,groupcode,size,packtype,direction,attributes)
end
elseif trace_callbacks then
local n = count_nodes(head,false)
- tracer("hpack","no chars",head,groupcode,n,n)
+ tracer("hpack",head,groupcode,n,n)
end
- return true
+ return head
end
- processors.hpack_filter = hpack_filter
+ processors.pre_linebreak_filter = pre_linebreak_filter
+ processors.hpack_filter = hpack_filter
do
- local setfield = nodes.setfield
- local hpack = nodes.hpack
+ local hpack = nodes.hpack
function nodes.fullhpack(head,...)
- local ok = hpack_filter(head)
- if not done or done == true then
- ok = head
- end
- local hp, b = hpack(ok,...)
- setfield(hp,"prev",nil)
- setfield(hp,"next",nil)
- return hp, b
+ return hpack((hpack_filter(head)),...)
end
end
do
- local setboth = nuts.setboth
- local hpack = nuts.hpack
+ local hpack = nuts.hpack
function nuts.fullhpack(head,...)
- local ok = hpack_filter(tonode(head))
- if not done or done == true then
- ok = head
- else
- ok = tonut(ok)
- end
- local hp, b = hpack(...)
- setboth(hp)
- return hp, b
+ return hpack(tonut(hpack_filter(tonode(head))),...)
end
end
- callbacks.register('pre_linebreak_filter', processors.pre_linebreak_filter, "all kind of horizontal manipulations (before par break)")
- callbacks.register('hpack_filter' , processors.hpack_filter, "all kind of horizontal manipulations (before hbox creation)")
+ callbacks.register('pre_linebreak_filter', pre_linebreak_filter, "horizontal manipulations (before par break)")
+ callbacks.register('hpack_filter' , hpack_filter, "horizontal manipulations (before hbox creation)")
end
do
+ -- Beware, these are packaged boxes so no first_glyph test needed. Maybe some day I'll add a hash
+ -- with valid groupcodes. Watch out, much can pass twice, for instance vadjust passes two times,
local actions = tasks.actions("finalizers") -- head, where
local count_nodes = nodes.countall
- -- beware, these are packaged boxes so no first_glyph test
- -- maybe some day a hash with valid groupcodes
- --
- -- beware, much can pass twice, for instance vadjust passes two times
- --
- -- something weird here .. group mvl when making a vbox
+ local tracer = processors.tracer
- function processors.post_linebreak_filter(head,groupcode)
+ local function post_linebreak_filter(head,groupcode)
if trace_callbacks then
local before = count_nodes(head,true)
- local head, done = actions(head,groupcode)
+ head = actions(head,groupcode)
local after = count_nodes(head,true)
- if done then
- tracer("post_linebreak","changed",head,groupcode,before,after,true)
- else
- tracer("post_linebreak","unchanged",head,groupcode,before,after,true)
- end
- return done and head or true
+ tracer("post_linebreak",head,groupcode,before,after,true)
else
- local head, done = actions(head,groupcode)
- return done and head or true
+ head = actions(head,groupcode)
end
+ return head
end
- callbacks.register('post_linebreak_filter', processors.post_linebreak_filter,"all kind of horizontal manipulations (after par break)")
+ processors.post_linebreak_filter = post_linebreak_filter
+
+ callbacks.register("post_linebreak_filter", post_linebreak_filter,"horizontal manipulations (after par break)")
end
do
- local texnest = tex.nest
+ local texnest = tex.nest
- local getlist = nodes.getlist
- local setlist = nodes.setlist
- local getsubtype = nodes.getsubtype
+ local getlist = nodes.getlist
+ local setlist = nodes.setlist
+ local getsubtype = nodes.getsubtype
- local line_code = nodes.listcodes.line
+ local linelist_code = nodes.listcodes.line
- local actions = tasks.actions("contributers")
+ local actions = tasks.actions("contributers")
function processors.contribute_filter(groupcode)
if groupcode == "box" then -- "pre_box"
local whatever = texnest[texnest.ptr]
if whatever then
local line = whatever.tail
- if line and getsubtype(line) == line_code then
+ if line and getsubtype(line) == linelist_code then
local head = getlist(line)
if head then
- local okay, done = actions(head,groupcode,line)
- if okay and okay ~= head then
- setlist(line,okay)
+ local result = actions(head,groupcode,line)
+ if result and result ~= head then
+ setlist(line,result)
end
end
end
@@ -229,7 +204,7 @@ do
end
end
- callbacks.register('contribute_filter', processors.contribute_filter,"things done with lines")
+ callbacks.register("contribute_filter", processors.contribute_filter,"things done with lines")
end
diff --git a/tex/context/base/mkiv/node-ref.lua b/tex/context/base/mkiv/node-ref.lua
index 1ec77e83d..e12bd95bd 100644
--- a/tex/context/base/mkiv/node-ref.lua
+++ b/tex/context/base/mkiv/node-ref.lua
@@ -67,21 +67,25 @@ local getattr = nuts.getattr
local setattr = nuts.setattr
local getsubtype = nuts.getsubtype
local getwhd = nuts.getwhd
-local getdir = nuts.getdir
+local getdirection = nuts.getdirection
local setshift = nuts.setshift
local getboxglue = nuts.getboxglue
local hpack_list = nuts.hpack
local vpack_list = nuts.vpack
-local list_dimensions = nuts.dimensions
-local list_rangedimensions = nuts.rangedimensions
+local getdimensions = nuts.dimensions
+local getrangedimensions = nuts.rangedimensions
local traverse = nuts.traverse
local find_node_tail = nuts.tail
local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
+local gluecodes = nodes.gluecodes
local listcodes = nodes.listcodes
+local dirvalues = nodes.dirvalues
+local lefttoright_code = dirvalues.lefttoright
+local righttoleft_code = dirvalues.righttoleft
+
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local glue_code = nodecodes.glue
@@ -90,11 +94,11 @@ local rule_code = nodecodes.rule
local dir_code = nodecodes.dir
local localpar_code = nodecodes.localpar
-local leftskip_code = skipcodes.leftskip
-local rightskip_code = skipcodes.rightskip
-local parfillskip_code = skipcodes.parfillskip
+local leftskip_code = gluecodes.leftskip
+local rightskip_code = gluecodes.rightskip
+local parfillskip_code = gluecodes.parfillskip
-local line_code = listcodes.line
+----- linelist_code = listcodes.line
local new_rule = nodepool.rule
local new_kern = nodepool.kern
@@ -113,9 +117,9 @@ local implement = interfaces.implement
local function hlist_dimensions(start,stop,parent)
local last = stop and getnext(stop)
if parent then
- return list_rangedimensions(parent,start,last)
+ return getrangedimensions(parent,start,last)
else
- return list_dimensions(start,last)
+ return getdimensions(start,last)
end
end
@@ -250,11 +254,13 @@ local function dimensions(parent,start,stop) -- in principle we could move some
end
end
--- is pardir important at all?
-
local function inject_range(head,first,last,reference,make,stack,parent,pardir,txtdir)
local width, height, depth, line = dimensions(parent,first,last)
- if txtdir == "+TRT" or (txtdir == "===" and pardir == "TRT") then -- KH: textdir == "===" test added
+ if txtdir == righttoleft_code then
+ width = - width
+ elseif textdir == lefttoright_code then
+ -- go on
+ elseif pardir == righttoleft_code then
width = - width
end
local result, resolved = make(width,height,depth,reference)
@@ -264,7 +270,7 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t
local l = getlist(line)
if trace_areas then
report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","line",
- reference,pardir or "---",txtdir or "---",
+ reference,pardir or "?",txtdir or "?",
tosequence(l,nil,true),width,height,depth)
end
setlist(line,result)
@@ -273,7 +279,7 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t
elseif head == first then
if trace_areas then
report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","head",
- reference,pardir or "---",txtdir or "---",
+ reference,pardir or "?",txtdir or "?",
tosequence(first,last,true),width,height,depth)
end
setlink(result,first)
@@ -281,7 +287,7 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t
else
if trace_areas then
report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","middle",
- reference,pardir or "---",txtdir or "---",
+ reference,pardir or "?",txtdir or "?",
tosequence(first,last,true),width,height,depth)
end
if first == last and getid(parent) == vlist_code and getid(first) == hlist_code then
@@ -306,7 +312,7 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir)
local correction = 0
local moveright = false
local first = getlist(current)
- if id == hlist_code then -- box_code line_code
+ if id == hlist_code then -- boxlist_code linelist_code
-- can be either an explicit hbox or a line and there is no way
-- to recognize this; anyway only if ht/dp (then inline)
local sr = stack[reference]
@@ -337,7 +343,7 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir)
correction = height + depth
height, depth = depth, height -- ugly hack, needed because pdftex backend does something funny
end
- if pardir == "TRT" then
+ if pardir == righttoleft_code then
width = - width
end
local result, resolved = make(width,height,depth,reference)
@@ -345,7 +351,7 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir)
if result and resolved then
if trace_areas then
report_area("%s: %04i %s %s %s: w=%p, h=%p, d=%p, c=%S","box",
- reference,pardir or "---",txtdir or "----","[]",width,height,depth,resolved)
+ reference,pardir or "?",txtdir or "?","[]",width,height,depth,resolved)
end
if not first then
setlist(current,result)
@@ -370,12 +376,6 @@ end
local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,txtdir) -- main
local first, last, firstdir, reference
- if not pardir then
- pardir = "==="
- end
- if not texdir then
- txtdir = "==="
- end
local current = head
while current do
local id = getid(current)
@@ -404,8 +404,8 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx
end
local list = getlist(current)
if list then
- local h, ok
- h, ok, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir)
+ local h
+ h, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir)
if h ~= current then
setlist(current,h)
end
@@ -416,9 +416,12 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx
elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left?
--
elseif id == dir_code then
- txtdir = getdir(current)
- elseif id == localpar_code then -- only test at begin
- pardir = getdir(current)
+ local direction, pop = getdirection(current)
+ txtdir = not pop and direction -- we might need a stack
+ elseif id == localpar_code then
+ if getsubtype(current) == 0 then
+ pardir = getdirection(current)
+ end
else
local r = getattr(current,attribute)
if not r then
@@ -441,46 +444,183 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx
if reference and (done[reference] or 0) == 0 then
head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
end
- return head, true, pardir, txtdir
+ return head, pardir, txtdir
end
--- local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir) -- singular !
--- if not pardir then
--- pardir = "==="
--- end
--- if not texdir then
--- txtdir = "==="
+-- -- not faster either:
+--
+-- local findattr = node.direct.find_attribute
+--
+-- local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,txtdir) -- main
+-- local first, last, firstdir, reference
+-- local someatt = findattr(head,attribute)
+-- if someatt then
+-- local current = head
+-- while current do
+-- local id = getid(current)
+-- if id == hlist_code or id == vlist_code then
+-- local r = getattr(current,attribute)
+-- -- test \goto{test}[page(2)] test \gotobox{test}[page(2)]
+-- -- test \goto{\TeX}[page(2)] test \gotobox{\hbox {x} \hbox {x}}[page(2)]
+-- -- if r and (not skip or r >) skip then -- maybe no > test
+-- -- inject_list(id,current,r,make,stack,pardir,txtdir)
+-- -- end
+-- if r then
+-- if not reference then
+-- reference, first, last, firstdir = r, current, current, txtdir
+-- elseif r == reference then
+-- -- same link
+-- last = current
+-- elseif (done[reference] or 0) == 0 then
+-- if not skip or r > skip then -- maybe no > test
+-- head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
+-- reference, first, last, firstdir = nil, nil, nil, nil
+-- end
+-- else
+-- reference, first, last, firstdir = r, current, current, txtdir
+-- end
+-- done[r] = (done[r] or 0) + 1
+-- end
+-- local list = getlist(current)
+-- if list then
+-- local h
+-- h, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir)
+-- if h ~= current then
+-- setlist(current,h)
+-- end
+-- end
+-- if r then
+-- done[r] = done[r] - 1
+-- end
+-- elseif id == dir_code then
+-- local direction, pop = getdirection(current)
+-- txtdir = not pop and direction -- we might need a stack
+-- elseif id == localpar_code then -- only test at begin
+-- pardir = getdirection(current)
+-- elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left?
+-- --
+-- else
+-- local r = getattr(current,attribute)
+-- if not r then
+-- -- just go on, can be kerns
+-- elseif not reference then
+-- reference, first, last, firstdir = r, current, current, txtdir
+-- elseif r == reference then
+-- last = current
+-- elseif (done[reference] or 0) == 0 then -- or id == glue_code and getsubtype(current) == right_skip_code
+-- if not skip or r > skip then -- maybe no > test
+-- head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
+-- reference, first, last, firstdir = nil, nil, nil, nil
+-- end
+-- else
+-- reference, first, last, firstdir = r, current, current, txtdir
+-- end
+-- end
+-- current = getnext(current)
+-- end
+-- if reference and (done[reference] or 0) == 0 then
+-- head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
+-- end
+-- else
+-- local current = head
+-- while current do
+-- local id = getid(current)
+-- if id == hlist_code or id == vlist_code then
+-- local list = getlist(current)
+-- if list then
+-- local h = inject_areas(list,attribute,make,stack,done,skip or 0,current,pardir,txtdir)
+-- if h ~= current then
+-- setlist(current,h)
+-- end
+-- end
+-- elseif id == dir_code then
+-- local direction, pop = getdirection(current)
+-- txtdir = not pop and direction -- we might need a stack
+-- elseif id == localpar_code then -- only test at begin
+-- pardir = getdirection(current)
+-- end
+-- current = getnext(current)
+-- end
-- end
+-- return head, pardir, txtdir
+-- end
+
+-- -- maybe first check for glyphs and use a goto:
+--
+-- local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,txtdir) -- main
+-- local first, last, firstdir, reference
-- local current = head
-- while current do
-- local id = getid(current)
--- if id == hlist_code or id == vlist_code then
--- local r = getattr(current,attribute)
--- if r and not done[r] then
--- done[r] = true
--- inject_list(id,current,r,make,stack,pardir,txtdir)
+-- local r -- else scope message due to goto
+-- if id == glyph_code then
+-- goto rest
+-- elseif id == hlist_code or id == vlist_code then
+-- r = getattr(current,attribute)
+-- -- test \goto{test}[page(2)] test \gotobox{test}[page(2)]
+-- -- test \goto{\TeX}[page(2)] test \gotobox{\hbox {x} \hbox {x}}[page(2)]
+-- -- if r and (not skip or r >) skip then -- maybe no > test
+-- -- inject_list(id,current,r,make,stack,pardir,txtdir)
+-- -- end
+-- if r then
+-- if not reference then
+-- reference, first, last, firstdir = r, current, current, txtdir
+-- elseif r == reference then
+-- -- same link
+-- last = current
+-- elseif (done[reference] or 0) == 0 then
+-- if not skip or r > skip then -- maybe no > test
+-- head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
+-- reference, first, last, firstdir = nil, nil, nil, nil
+-- end
+-- else
+-- reference, first, last, firstdir = r, current, current, txtdir
+-- end
+-- done[r] = (done[r] or 0) + 1
-- end
-- local list = getlist(current)
-- if list then
--- local h = inject_area(list,attribute,make,stack,done,current,pardir,txtdir)
+-- local h
+-- h, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir)
-- if h ~= current then
-- setlist(current,h)
-- end
-- end
+-- if r then
+-- done[r] = done[r] - 1
+-- end
+-- elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left?
+-- --
-- elseif id == dir_code then
--- txtdir = getdir(current)
--- elseif id == localpar_code then
--- pardir = getdir(current)
--- else
--- local r = getattr(current,attribute)
--- if r and not done[r] then
--- done[r] = true
--- head, current = inject_range(head,current,current,r,make,stack,parent,pardir,txtdir)
+-- local direction, pop = getdirection(current)
+-- txtdir = not pop and direction -- we might need a stack
+-- elseif id == localpar_code then -- only test at begin
+-- pardir = getdirection(current)
+-- end
+-- goto next
+-- ::rest::
+-- r = getattr(current,attribute)
+-- if not r then
+-- -- just go on, can be kerns
+-- elseif not reference then
+-- reference, first, last, firstdir = r, current, current, txtdir
+-- elseif r == reference then
+-- last = current
+-- elseif (done[reference] or 0) == 0 then -- or id == glue_code and getsubtype(current) == right_skip_code
+-- if not skip or r > skip then -- maybe no > test
+-- head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
+-- reference, first, last, firstdir = nil, nil, nil, nil
-- end
+-- else
+-- reference, first, last, firstdir = r, current, current, txtdir
-- end
+-- ::next::
-- current = getnext(current)
-- end
--- return head, true
+-- if reference and (done[reference] or 0) == 0 then
+-- head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
+-- end
+-- return head, pardir, txtdir
-- end
-- tracing: todo: use predefined colors
@@ -595,11 +735,11 @@ nodes.references = {
-- todo: get rid of n (n is just a number, can be used for tracing, obsolete)
-local function setreference(h,d,r)
+local function setreference(h,d,r) -- h and d can be nil
topofstack = topofstack + 1
-- the preroll permits us to determine samepage (but delayed also has some advantages)
-- so some part of the backend work is already done here
- stack[topofstack] = { r, h, d, codeinjections.prerollreference(r) }
+ stack[topofstack] = { r, h or false, d or false, codeinjections.prerollreference(r) }
-- texsetattribute(attribute,topofstack) -- todo -> at tex end
texsetcount("lastreferenceattribute",topofstack)
end
@@ -615,7 +755,11 @@ local function makereference(width,height,depth,reference) -- height and depth a
if trace_references then
report_reference("resolving attribute %a",reference)
end
- local resolved, ht, dp, set, n = sr[1], sr[2], sr[3], sr[4], sr[5]
+ local resolved = sr[1]
+ local ht = sr[2]
+ local dp = sr[3]
+ local set = sr[4]
+ local n = sr[5]
-- logs.report("temp","child: ht=%p dp=%p, parent: ht=%p dp=%p",ht,dp,height,depth)
if ht then
if height < ht then height = ht end
@@ -672,11 +816,9 @@ end
function nodes.references.handler(head)
if head and topofstack > 0 then
- local head = tonut(head)
- local head, done = inject_areas(head,attribute,makereference,stack,done)
- return tonode(head), done
+ return (inject_areas(head,attribute,makereference,stack,done))
else
- return head, false
+ return head
end
end
@@ -706,7 +848,11 @@ local function makedestination(width,height,depth,reference)
if trace_destinations then
report_destination("resolving attribute %a",reference)
end
- local resolved, ht, dp, name, view = sr[1], sr[2], sr[3], sr[4], sr[5] -- sr[4] will change to just internal
+ local resolved = sr[1]
+ local ht = sr[2]
+ local dp = sr[3]
+ local name = sr[4]
+ local view = sr[5]
if ht then
if height < ht then height = ht end
if depth < dp then depth = dp end
@@ -783,21 +929,12 @@ local function makedestination(width,height,depth,reference)
end
end
--- function nodes.destinations.handler(head)
--- if head and topofstack > 0 then
--- return inject_area(head,attribute,makedestination,stack,done) -- singular
--- else
--- return head, false
--- end
--- end
function nodes.destinations.handler(head)
if head and topofstack > 0 then
- local head = tonut(head)
- local head, done = inject_areas(head,attribute,makedestination,stack,done)
- return tonode(head), done
+ return (inject_areas(head,attribute,makedestination,stack,done))
else
- return head, false
+ return head
end
end
@@ -907,15 +1044,3 @@ statistics.register("interactive elements", function()
return nil
end
end)
-
-function references.enableinteraction()
- enableaction("shipouts","nodes.references.handler")
- enableaction("shipouts","nodes.destinations.handler")
- function references.enableinteraction() end
-end
-
-implement {
- name = "enableinteraction",
- actions = references.enableinteraction,
- onlyonce = true
-}
diff --git a/tex/context/base/mkiv/node-res.lua b/tex/context/base/mkiv/node-res.lua
index a6211e80e..d9999968a 100644
--- a/tex/context/base/mkiv/node-res.lua
+++ b/tex/context/base/mkiv/node-res.lua
@@ -6,6 +6,7 @@ if not modules then modules = { } end modules ['node-res'] = {
license = "see context related readme files"
}
+local type, next = type, next
local gmatch, format = string.gmatch, string.format
--[[ldx--
@@ -13,34 +14,39 @@ local gmatch, format = string.gmatch, string.format
for debugging <l n='luatex'/> node management.</p>
--ldx]]--
-local report_nodes = logs.reporter("nodes","housekeeping")
-
local nodes, node = nodes, node
-nodes.pool = nodes.pool or { }
-local nodepool = nodes.pool
+local report_nodes = logs.reporter("nodes","housekeeping")
-local whatsitcodes = nodes.whatsitcodes
-local skipcodes = nodes.skipcodes
-local kerncodes = nodes.kerncodes
-local rulecodes = nodes.rulecodes
-local nodecodes = nodes.nodecodes
-local gluecodes = nodes.gluecodes
-local boundarycodes = nodes.boundarycodes
-local usercodes = nodes.usercodes
+nodes.pool = nodes.pool or { }
+local nodepool = nodes.pool
-local glyph_code = nodecodes.glyph
+local whatsitcodes = nodes.whatsitcodes
+local gluecodes = nodes.gluecodes
+local kerncodes = nodes.kerncodes
+local rulecodes = nodes.rulecodes
+local nodecodes = nodes.nodecodes
+local leadercodes = nodes.leadercodes
+local boundarycodes = nodes.boundarycodes
+local usercodes = nodes.usercodes
-local allocate = utilities.storage.allocate
+local nodeproperties = nodes.properties.data
-local texgetcount = tex.getcount
+local glyph_code = nodecodes.glyph
+local rule_code = nodecodes.rule
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local whatsit_code = nodecodes.whatsit
-local reserved, nofreserved = { }, 0
+local currentfont = font.current
+local texgetcount = tex.getcount
--- user nodes
+local allocate = utilities.storage.allocate
-local userids = allocate()
-local lastid = 0
+local reserved = { }
+local nofreserved = 0
+local userids = allocate()
+local lastid = 0
setmetatable(userids, {
__index = function(t,k)
@@ -89,6 +95,9 @@ local setwidth = nuts.setwidth
local setsubtype = nuts.setsubtype
local setleader = nuts.setleader
+local setdata = nuts.setdata
+local setvalue = nuts.setvalue
+
local copy_nut = nuts.copy
local new_nut = nuts.new
local flush_nut = nuts.flush
@@ -147,68 +156,68 @@ nutpool.register = register_node -- could be register_nut
-- so far
-local disc = register_nut(new_nut("disc"))
-local kern = register_nut(new_nut("kern",kerncodes.userkern))
-local fontkern = register_nut(new_nut("kern",kerncodes.fontkern))
-local italickern = register_nut(new_nut("kern",kerncodes.italiccorrection))
-local penalty = register_nut(new_nut("penalty"))
-local glue = register_nut(new_nut("glue")) -- glue.spec = nil
-local glue_spec = register_nut(new_nut("glue_spec"))
-local glyph = register_nut(new_nut("glyph",0))
+local disc = register_nut(new_nut(nodecodes.disc))
+local kern = register_nut(new_nut(kern_code,kerncodes.userkern))
+local fontkern = register_nut(new_nut(kern_code,kerncodes.fontkern))
+local italickern = register_nut(new_nut(kern_code,kerncodes.italiccorrection))
+local penalty = register_nut(new_nut(nodecodes.penalty))
+local glue = register_nut(new_nut(glue_code)) -- glue.spec = nil
+local glue_spec = register_nut(new_nut(nodecodes.gluespec))
+local glyph = register_nut(new_nut(glyph_code,0))
-local textdir = register_nut(new_nut("dir"))
+local textdir = register_nut(new_nut(nodecodes.dir))
-local latelua = register_nut(new_nut("whatsit",whatsitcodes.latelua))
-local special = register_nut(new_nut("whatsit",whatsitcodes.special))
+local latelua = register_nut(new_nut(whatsit_code,whatsitcodes.latelua))
+local savepos = register_nut(new_nut(whatsit_code,whatsitcodes.savepos))
-local user_node = new_nut("whatsit",whatsitcodes.userdefined)
+local user_node = new_nut(whatsit_code,whatsitcodes.userdefined)
-local user_number = register_nut(copy_nut(user_node)) setfield(user_number, "type",usercodes.number)
-local user_nodes = register_nut(copy_nut(user_node)) setfield(user_nodes, "type",usercodes.node)
-local user_string = register_nut(copy_nut(user_node)) setfield(user_string, "type",usercodes.string)
-local user_tokens = register_nut(copy_nut(user_node)) setfield(user_tokens, "type",usercodes.token)
------ user_lua = register_nut(copy_nut(user_node)) setfield(user_lua, "type",usercodes.lua) -- in > 0.95
-local user_attributes = register_nut(copy_nut(user_node)) setfield(user_attributes,"type",usercodes.attribute)
+if CONTEXTLMTXMODE < 2 then
+ setfield(user_node,"type",usercodes.number)
+end
-local left_margin_kern = register_nut(new_nut("margin_kern",0))
-local right_margin_kern = register_nut(new_nut("margin_kern",1))
+local left_margin_kern = register_nut(new_nut(nodecodes.marginkern,0))
+local right_margin_kern = register_nut(new_nut(nodecodes.marginkern,1))
-local lineskip = register_nut(new_nut("glue",skipcodes.lineskip))
-local baselineskip = register_nut(new_nut("glue",skipcodes.baselineskip))
-local leftskip = register_nut(new_nut("glue",skipcodes.leftskip))
-local rightskip = register_nut(new_nut("glue",skipcodes.rightskip))
+local lineskip = register_nut(new_nut(glue_code,gluecodes.lineskip))
+local baselineskip = register_nut(new_nut(glue_code,gluecodes.baselineskip))
+local leftskip = register_nut(new_nut(glue_code,gluecodes.leftskip))
+local rightskip = register_nut(new_nut(glue_code,gluecodes.rightskip))
-local temp = register_nut(new_nut("temp",0))
+local temp = register_nut(new_nut(nodecodes.temp,0))
-local noad = register_nut(new_nut("noad"))
-local delimiter = register_nut(new_nut("delim"))
-local fence = register_nut(new_nut("fence"))
-local submlist = register_nut(new_nut("sub_mlist"))
-local accent = register_nut(new_nut("accent"))
-local radical = register_nut(new_nut("radical"))
-local fraction = register_nut(new_nut("fraction"))
-local subbox = register_nut(new_nut("sub_box"))
-local mathchar = register_nut(new_nut("math_char"))
-local mathtextchar = register_nut(new_nut("math_text_char"))
-local choice = register_nut(new_nut("choice"))
+local noad = register_nut(new_nut(nodecodes.noad))
+local delimiter = register_nut(new_nut(nodecodes.delim))
+local fence = register_nut(new_nut(nodecodes.fence))
+local submlist = register_nut(new_nut(nodecodes.submlist))
+local accent = register_nut(new_nut(nodecodes.accent))
+local radical = register_nut(new_nut(nodecodes.radical))
+local fraction = register_nut(new_nut(nodecodes.fraction))
+local subbox = register_nut(new_nut(nodecodes.subbox))
+local mathchar = register_nut(new_nut(nodecodes.mathchar))
+local mathtextchar = register_nut(new_nut(nodecodes.mathtextchar))
+local choice = register_nut(new_nut(nodecodes.choice))
-local boundary = register_nut(new_nut("boundary",boundarycodes.user))
-local wordboundary = register_nut(new_nut("boundary",boundarycodes.word))
+local boundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.user))
+local wordboundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.word))
-local cleader = register_nut(copy_nut(glue)) setsubtype(cleader,gluecodes.cleaders) setglue(cleader,0,65536,0,2,0)
+local cleader = register_nut(copy_nut(glue)) setsubtype(cleader,leadercodes.cleaders) setglue(cleader,0,65536,0,2,0)
-- the dir field needs to be set otherwise crash:
-local rule = register_nut(new_nut("rule")) setdir(rule, "TLT")
-local emptyrule = register_nut(new_nut("rule",rulecodes.empty)) setdir(rule, "TLT")
-local userrule = register_nut(new_nut("rule",rulecodes.user)) setdir(rule, "TLT")
-local hlist = register_nut(new_nut("hlist")) setdir(hlist,"TLT")
-local vlist = register_nut(new_nut("vlist")) setdir(vlist,"TLT")
+local lefttoright_code = nodes.dirvalues.lefttoright
+
+local rule = register_nut(new_nut(rule_code)) setdirection(rule, lefttoright_code)
+local emptyrule = register_nut(new_nut(rule_code,rulecodes.empty)) setdirection(rule, lefttoright_code)
+local userrule = register_nut(new_nut(rule_code,rulecodes.user)) setdirection(rule, lefttoright_code)
+local outlinerule = register_nut(new_nut(rule_code,rulecodes.outline)) setdirection(rule, lefttoright_code)
+local hlist = register_nut(new_nut(nodecodes.hlist)) setdirection(hlist,lefttoright_code)
+local vlist = register_nut(new_nut(nodecodes.vlist)) setdirection(vlist,lefttoright_code)
function nutpool.glyph(fnt,chr)
local n = copy_nut(glyph)
if fnt then
- setfont(n,fnt,chr)
+ setfont(n,fnt == true and currentfont() or fnt,chr)
elseif chr then
setchar(n,chr)
end
@@ -234,7 +243,7 @@ end
function nutpool.boundary(v)
local n = copy_nut(boundary)
if v and v ~= 0 then
- setfield(n,"value",v)
+ setvalue(n,v)
end
return n
end
@@ -242,7 +251,7 @@ end
function nutpool.wordboundary(v)
local n = copy_nut(wordboundary)
if v and v ~= 0 then
- setfield(n,"value",v)
+ setvalue(n,v)
end
return n
end
@@ -335,7 +344,7 @@ function nutpool.disc(pre,post,replace)
return d
end
-function nutpool.textdir(dir)
+function nutpool.textdir(dir) -- obsolete !
local t = copy_nut(textdir)
if dir then
setdir(t,dir)
@@ -355,35 +364,49 @@ function nutpool.direction(dir,swap)
return t
end
-function nutpool.rule(width,height,depth,dir) -- w/h/d == nil will let them adapt
+function nutpool.rule(width,height,depth,direction) -- w/h/d == nil will let them adapt
local n = copy_nut(rule)
if width or height or depth then
setwhd(n,width,height,depth)
end
- if dir then
- setdir(n,dir)
+ if direction then
+ setdirection(n,direction)
end
return n
end
-function nutpool.emptyrule(width,height,depth,dir) -- w/h/d == nil will let them adapt
+function nutpool.emptyrule(width,height,depth,direction) -- w/h/d == nil will let them adapt
local n = copy_nut(emptyrule)
if width or height or depth then
setwhd(n,width,height,depth)
end
- if dir then
- setdir(n,dir)
+ if direction then
+ setdirection(n,direction)
end
return n
end
-function nutpool.userrule(width,height,depth,dir) -- w/h/d == nil will let them adapt
+function nutpool.userrule(width,height,depth,direction) -- w/h/d == nil will let them adapt
local n = copy_nut(userrule)
if width or height or depth then
setwhd(n,width,height,depth)
end
- if dir then
- setdir(n,dir)
+ if direction then
+ setdirection(n,direction)
+ end
+ return n
+end
+
+function nutpool.outlinerule(width,height,depth,line,direction) -- w/h/d == nil will let them adapt
+ local n = copy_nut(outlinerule)
+ if width or height or depth then
+ setwhd(n,width,height,depth)
+ end
+ if line then
+ setfield(n,"transform",line)
+ end
+ if direction then
+ setdirection(n,direction)
end
return n
end
@@ -399,13 +422,32 @@ function nutpool.leader(width,list)
return n
end
-function nutpool.latelua(code)
- local n = copy_nut(latelua)
- setfield(n,"string",code)
- return n
+function nutpool.savepos()
+ return copy_nut(savepos)
end
-nutpool.lateluafunction = nutpool.latelua
+if CONTEXTLMTXMODE > 1 then
+
+ function nutpool.latelua(code)
+ local n = copy_nut(latelua)
+ nodeproperties[n] = { data = code }
+ return n
+ end
+
+else
+
+ function nutpool.latelua(code)
+ local n = copy_nut(latelua)
+ if type(code) == "table" then
+ local action = code.action
+ local specification = code.specification or code
+ code = function() action(specification) end
+ end
+ setdata(n,code)
+ return n
+ end
+
+end
function nutpool.leftmarginkern(glyph,width)
local n = copy_nut(left_margin_kern)
@@ -494,86 +536,21 @@ function nodepool.vlist(list,width,height,depth,shift)
return tonode(new_vlist(list and tonut(list),width,height,depth,shift))
end
--- local num = userids["my id"]
--- local str = userids[num]
-
-function nutpool.usernumber(id,num)
- local n = copy_nut(user_number)
- if num then
- setfield(n,"user_id",id)
- setfield(n,"value",num)
- elseif id then
- setfield(n,"value",id)
- end
- return n
-end
-
-function nutpool.userlist(id,list)
- local n = copy_nut(user_nodes)
- if list then
- setfield(n,"user_id",id)
- setfield(n,"value",list)
- else
- setfield(n,"value",id)
- end
- return n
-end
-
-function nutpool.userstring(id,str)
- local n = copy_nut(user_string)
- if str then
- setfield(n,"user_id",id)
- setfield(n,"value",str)
- else
- setfield(n,"value",id)
- end
- return n
-end
-
-function nutpool.usertokens(id,tokens)
- local n = copy_nut(user_tokens)
- if tokens then
- setfield(n,"user_id",id)
- setfield(n,"value",tokens)
- else
- setfield(n,"value",id)
- end
- return n
-end
-
-function nutpool.userlua(id,code)
- local n = copy_nut(user_lua)
- if code then
- setfield(n,"user_id",id)
- setfield(n,"value",code)
- else
- setfield(n,"value",id)
- end
- return n
-end
-
-function nutpool.userattributes(id,attr)
- local n = copy_nut(user_attributes)
- if attr then
- setfield(n,"user_id",id)
- setfield(n,"value",attr)
- else
- setfield(n,"value",id)
- end
- return n
-end
-
-function nutpool.special(str)
- local n = copy_nut(special)
- setfield(n,"data",str)
+function nutpool.usernode(id,data)
+ local n = copy_nut(user_node)
+ nodeproperties[n] = {
+ id = id,
+ data = data,
+ }
return n
end
-- housekeeping
local function cleanup(nofboxes) -- todo
- if nodes.tracers.steppers then -- to be resolved
- nodes.tracers.steppers.reset() -- todo: make a registration subsystem
+ local tracers = nodes.tracers
+ if tracers and tracers.steppers then -- to be resolved
+ tracers.steppers.reset() -- todo: make a registration subsystem
end
local nl = 0
local nr = nofreserved
@@ -624,3 +601,45 @@ statistics.register("node memory usage", function() -- comes after cleanup !
end)
lua.registerfinalizer(cleanup, "cleanup reserved nodes")
+
+-- experiment
+
+do
+
+ local glyph = tonode(glyph)
+ local traverse_id = nodes.traverse_id
+
+ local traversers = table.setmetatableindex(function(t,k)
+ local v = traverse_id(type(k) == "number" and k or nodecodes[k],glyph)
+ t[k] = v
+ return v
+ end)
+
+ traversers.node = nodes.traverse (glyph)
+ traversers.char = nodes.traverse_char (glyph)
+ if nuts.traverse_glyph then traversers.glyph = nodes.traverse_glyph(glyph) end
+ if nuts.traverse_list then traversers.list = nodes.traverse_list (glyph) end
+
+ nodes.traversers = traversers
+
+end
+
+do
+
+ local glyph = glyph
+ local traverse_id = nuts.traverse_id
+
+ local traversers = table.setmetatableindex(function(t,k)
+ local v = traverse_id(type(k) == "number" and k or nodecodes[k],glyph)
+ t[k] = v
+ return v
+ end)
+
+ traversers.node = nuts.traverse (glyph)
+ traversers.char = nuts.traverse_char (glyph)
+ if nuts.traverse_glyph then traversers.glyph = nuts.traverse_glyph(glyph) end
+ if nuts.traverse_list then traversers.list = nuts.traverse_list (glyph) end
+
+ nuts.traversers = traversers
+
+end
diff --git a/tex/context/base/mkiv/node-rul.lua b/tex/context/base/mkiv/node-rul.lua
index 2b0368c2b..ea0e5c7a0 100644
--- a/tex/context/base/mkiv/node-rul.lua
+++ b/tex/context/base/mkiv/node-rul.lua
@@ -37,18 +37,20 @@ local setlink = nuts.setlink
local getnext = nuts.getnext
local getprev = nuts.getprev
local getid = nuts.getid
-local getdir = nuts.getdir
+local getdirection = nuts.getdirection
local getattr = nuts.getattr
local setattr = nuts.setattr
local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
local getlist = nuts.getlist
local setwhd = nuts.setwhd
-local setdir = nuts.setdir
local setattrlist = nuts.setattrlist
local setshift = nuts.setshift
local getwidth = nuts.getwidth
local setwidth = nuts.setwidth
+local setfield = nuts.setfield
+
+local isglyph = nuts.isglyph
local flushlist = nuts.flush_list
local effective_glue = nuts.effective_glue
@@ -56,17 +58,16 @@ local insert_node_after = nuts.insert_after
local insert_node_before = nuts.insert_before
local find_tail = nuts.tail
local setglue = nuts.setglue
-local traverse_id = nuts.traverse_id
-local list_dimensions = nuts.rangedimensions
+local getrangedimensions = nuts.rangedimensions
local hpack_nodes = nuts.hpack
-local current_attr = nuts.current_attr
local copy_list = nuts.copy_list
+local nexthlist = nuts.traversers.hlist
+
local nodecodes = nodes.nodecodes
local rulecodes = nodes.rulecodes
local gluecodes = nodes.gluecodes
local listcodes = nodes.listcodes
-local kerncodes = nodes.kerncodes
local glyph_code = nodecodes.glyph
local localpar_code = nodecodes.localpar
@@ -74,8 +75,8 @@ local dir_code = nodecodes.dir
local glue_code = nodecodes.glue
local hlist_code = nodecodes.hlist
-local indent_code = listcodes.indent
-local line_code = listcodes.line
+local indentlist_code = listcodes.indent
+local linelist_code = listcodes.line
local leftskip_code = gluecodes.leftskip
local rightskip_code = gluecodes.rightskip
@@ -121,8 +122,8 @@ local setmetatableindex = table.setmetatableindex
--
-local striprange = nodes.striprange
-local processwords = nodes.processwords
+local striprange = nuts.striprange
+local processwords = nuts.processwords
--
@@ -144,7 +145,7 @@ local function usernutrule(t,noattributes)
if noattributes == false or noattributes == nil then
-- avoid fuzzy ones
else
- setattrlist(r,current_attr())
+ setattrlist(r,true)
end
properties[r] = t
return r
@@ -156,9 +157,11 @@ local function userrule(t,noattributes)
return tonode(usernutrule(t,noattributes))
end
-rules.userrule = userrule
-local ruleactions = { }
-rules.ruleactions = ruleactions
+rules.userrule = userrule
+local ruleactions = { }
+
+rules .ruleactions = ruleactions
+nutrules.ruleactions = ruleactions -- convenient
local function mathradical(n,h,v)
----- size = getfield(n,"index")
@@ -203,18 +206,18 @@ local subtypeactions = {
[rulecodes.radical] = mathradical,
}
-callbacks.register(
- "process_rule",
- function(n,h,v)
- local n = tonut(n)
- local s = getsubtype(n)
- local a = subtypeactions[s]
- if a then
- a(n,h,v)
- end
- end,
- "handle additional user rule features"
-)
+local function process_rule(n,h,v)
+ local n = tonut(n)
+ local s = getsubtype(n)
+ local a = subtypeactions[s]
+ if a then
+ a(n,h,v)
+ end
+end
+
+callbacks.register("process_rule",process_rule,"handle additional user rule features")
+
+callbacks.functions.process_rule = process_rule
--
@@ -239,9 +242,9 @@ end
local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but acceptable for this purpose
local font = nil
- local id = getid(f)
- if id == glyph_code then
- font = getfont(f)
+ local char, id = isglyph(f)
+ if char then
+ font = id
elseif id == hlist_code then
font = getattr(f,a_runningtext)
end
@@ -263,7 +266,7 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a
if not f then
return head
end
- local w, ht, dp = list_dimensions(parent,f,getnext(l))
+ local w, ht, dp = getrangedimensions(parent,f,getnext(l))
local method = d.method
local empty = d.empty == v_yes
local offset = d.offset
@@ -331,7 +334,7 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a
end
end
if mp and mp ~= "" then
- local r = userrule {
+ local r = usernutrule {
width = w,
height = ht,
depth = dp,
@@ -344,16 +347,17 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a
ca = color,
ta = transparency,
}
- inject(tonut(r),w,ht,dp)
+ inject(r,w,ht,dp)
else
local tx = d.text
if tx then
- tx = copy_list(tx)
+ local l = copy_list(tx)
if d["repeat"] == v_yes then
- tx = new_leader(w,tx)
+ l = new_leader(w,l)
+ setattrlist(l,tx)
end
- local r = hpack_nodes(tx,w,"exactly")
- inject(r,w,ht,dp)
+ l = hpack_nodes(l,w,"exactly")
+ inject(l,w,ht,dp)
else
for i=1,level do
local ht = (offset+(i-1)*dy)*e + rulethickness - m
@@ -373,10 +377,8 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a
return head
end
-local process = nodes.processwords
-
rules.handler = function(head)
- return process(a_ruled,data,flush_ruled,head)
+ return processwords(a_ruled,data,flush_ruled,head)
end
function rules.enable()
@@ -409,7 +411,7 @@ local function flush_shifted(head,first,last,data,level,parent,strip) -- not tha
local next = getnext(last)
setprev(first)
setnext(last)
- local width, height, depth = list_dimensions(parent,first,next)
+ local width, height, depth = getrangedimensions(parent,first,next)
local list = hpack_nodes(first,width,"exactly") -- we can use a simple pack
if first == head then
head = list
@@ -429,9 +431,9 @@ local function flush_shifted(head,first,last,data,level,parent,strip) -- not tha
return head
end
-local process = nodes.processwords
-
-nodes.shifts.handler = function(head) return process(a_shifted,data,flush_shifted,head) end
+nodes.shifts.handler = function(head)
+ return processwords(a_shifted,data,flush_shifted,head)
+end
function nodes.shifts.enable()
enableaction("shipouts","nodes.shifts.handler")
@@ -459,7 +461,7 @@ local function linefiller(current,data,width,location)
local ca = data.ca
local ta = data.ta
if mp and mp ~= "" then
- return tonut(userrule {
+ return usernutrule {
width = width,
height = height,
depth = depth,
@@ -470,18 +472,56 @@ local function linefiller(current,data,width,location)
ca = ca,
ta = ta,
option = location,
- direction = getdir(current),
- })
+ direction = getdirection(current),
+ }
else
- local linefiller = new_rule(width,height,depth)
+ local rule = new_rule(width,height,depth)
if ca then
- setattr(linefiller,a_colorspace,ma)
- setattr(linefiller,a_color,ca)
+ setattr(rule,a_colorspace,ma)
+ setattr(rule,a_color,ca)
end
if ta then
- setattr(linefiller,a_transparency,ta)
+ setattr(rule,a_transparency,ta)
+ end
+ return rule
+ end
+end
+
+function nodes.linefillers.filler(current,data,width,height,depth)
+ if width and width > 0 then
+ local height = height or data.height or 0
+ local depth = depth or data.depth or 0
+ if (height + depth) ~= 0 then
+ local mp = data.mp
+ local ma = data.ma
+ local ca = data.ca
+ local ta = data.ta
+ if mp and mp ~= "" then
+ return usernutrule {
+ width = width,
+ height = height,
+ depth = depth,
+ type = "mp",
+ line = data.rulethickness,
+ data = mp,
+ ma = ma,
+ ca = ca,
+ ta = ta,
+ option = location,
+ direction = getdirection(current),
+ }
+ else
+ local rule = new_rule(width,height,depth)
+ if ca then
+ setattr(rule,a_colorspace,ma)
+ setattr(rule,a_color,ca)
+ end
+ if ta then
+ setattr(rule,a_transparency,ta)
+ end
+ return rule
+ end
end
- return linefiller
end
end
@@ -496,119 +536,115 @@ local function find_attr(head,attr)
end
function nodes.linefillers.handler(head)
--- local current = tonut(head) -- when we hook into the contributers
- for current in traverse_id(hlist_code,tonut(head)) do
- if getsubtype(current) == line_code then
- local list = getlist(current)
- if list then
- -- why doesn't leftskip take the attributes
- -- or list[linefiller] or maybe first match (maybe we need a fast helper for that)
- local a = getattr(current,a_linefiller)
- if a then
- local class = a % 1000
- local data = data[class]
- if data then
- local location = data.location
- local scope = data.scope
- local distance = data.distance
- local threshold = data.threshold
- local leftlocal = false
- local rightlocal = false
- --
- if scope == v_right then
- leftlocal = true
- elseif scope == v_left then
- rightlocal = true
- elseif scope == v_local then
- leftlocal = true
- rightlocal = true
- end
- --
- if location == v_left or location == v_both then
- local lskip = nil -- leftskip
- local iskip = nil -- indentation
- local head = list
- while head do
- local id = getid(head)
- if id == glue_code then
- if getsubtype(head) == leftskip_code then
- lskip = head
- else
- break
- end
- elseif id == localpar_code or id == dir_code then
- -- go on
- elseif id == hlist_code then
- if getsubtype(head) == indent_code then
- iskip = head
- end
- break
+ for current, subtype, list in nexthlist, head do
+ if list and subtype == linelist_code then
+ -- why doesn't leftskip take the attributes
+ -- or list[linefiller] or maybe first match (maybe we need a fast helper for that)
+ local a = getattr(current,a_linefiller)
+ if a then
+ local class = a % 1000
+ local data = data[class]
+ if data then
+ local location = data.location
+ local scope = data.scope
+ local distance = data.distance
+ local threshold = data.threshold
+ local leftlocal = false
+ local rightlocal = false
+ --
+ if scope == v_right then
+ leftlocal = true
+ elseif scope == v_left then
+ rightlocal = true
+ elseif scope == v_local then
+ leftlocal = true
+ rightlocal = true
+ end
+ --
+ if location == v_left or location == v_both then
+ local lskip = nil -- leftskip
+ local iskip = nil -- indentation
+ local head = list
+ while head do
+ local id = getid(head)
+ if id == glue_code then
+ if getsubtype(head) == leftskip_code then
+ lskip = head
else
break
end
- head = getnext(head)
+ elseif id == localpar_code or id == dir_code then
+ -- go on
+ elseif id == hlist_code then
+ if getsubtype(head) == indentlist_code then
+ iskip = head
+ end
+ break
+ else
+ break
end
- if head then
- local indentation = iskip and getwidth(iskip) or 0
- local leftfixed = lskip and getwidth(lskip) or 0
- local lefttotal = lskip and effective_glue(lskip,current) or 0
- local width = lefttotal - (leftlocal and leftfixed or 0) + indentation - distance
- if width > threshold then
- if iskip then
- setwidth(iskip,0)
+ head = getnext(head)
+ end
+ if head then
+ local indentation = iskip and getwidth(iskip) or 0
+ local leftfixed = lskip and getwidth(lskip) or 0
+ local lefttotal = lskip and effective_glue(lskip,current) or 0
+ local width = lefttotal - (leftlocal and leftfixed or 0) + indentation - distance
+ if width > threshold then
+ if iskip then
+ setwidth(iskip,0)
+ end
+ if lskip then
+ setglue(lskip,leftlocal and getwidth(lskip) or nil)
+ if distance > 0 then
+ insert_node_after(list,lskip,new_kern(distance))
end
- if lskip then
- setglue(lskip,leftlocal and getwidth(lskip) or nil)
- if distance > 0 then
- insert_node_after(list,lskip,new_kern(distance))
- end
- insert_node_after(list,lskip,linefiller(current,data,width,"left"))
- else
- insert_node_before(list,head,linefiller(current,data,width,"left"))
- if distance > 0 then
- insert_node_before(list,head,new_kern(distance))
- end
+ insert_node_after(list,lskip,linefiller(current,data,width,"left"))
+ else
+ insert_node_before(list,head,linefiller(current,data,width,"left"))
+ if distance > 0 then
+ insert_node_before(list,head,new_kern(distance))
end
end
end
end
- --
- if location == v_right or location == v_both then
- local pskip = nil -- parfillskip
- local rskip = nil -- rightskip
- local tail = find_tail(list)
- while tail and getid(tail) == glue_code do
- local subtype = getsubtype(tail)
- if subtype == rightskip_code then
- rskip = tail
- elseif subtype == parfillskip_code then
- pskip = tail
- else
- break
- end
- tail = getprev(tail)
+ end
+ --
+ if location == v_right or location == v_both then
+ local pskip = nil -- parfillskip
+ local rskip = nil -- rightskip
+ local tail = find_tail(list)
+ while tail and getid(tail) == glue_code do
+ local subtype = getsubtype(tail)
+ if subtype == rightskip_code then
+ rskip = tail
+ elseif subtype == parfillskip_code then
+ pskip = tail
+ else
+ break
end
- if tail then
- local rightfixed = rskip and getwidth(rskip) or 0
- local righttotal = rskip and effective_glue(rskip,current) or 0
- local parfixed = pskip and getwidth(pskip) or 0
- local partotal = pskip and effective_glue(pskip,current) or 0
- local width = righttotal - (rightlocal and rightfixed or 0) + partotal - distance
- if width > threshold then
- if pskip then
- setglue(pskip)
+ tail = getprev(tail)
+ end
+ if tail then
+ local rightfixed = rskip and getwidth(rskip) or 0
+ local righttotal = rskip and effective_glue(rskip,current) or 0
+ local parfixed = pskip and getwidth(pskip) or 0
+ local partotal = pskip and effective_glue(pskip,current) or 0
+ local width = righttotal - (rightlocal and rightfixed or 0) + partotal - distance
+ if width > threshold then
+ if pskip then
+ setglue(pskip)
+ end
+ if rskip then
+ setglue(rskip,rightlocal and getwidth(rskip) or nil)
+ if distance > 0 then
+ insert_node_before(list,rskip,new_kern(distance))
end
- if rskip then
- setglue(rskip,rightlocal and getwidth(rskip) or nil)
- if distance > 0 then
- insert_node_before(list,rskip,new_kern(distance))
- end
- insert_node_before(list,rskip,linefiller(current,data,width,"right"))
- else
- insert_node_after(list,tail,linefiller(current,data,width,"right"))
- if distance > 0 then
- insert_node_after(list,tail,new_kern(distance))
- end
+ insert_node_before(list,rskip,linefiller(current,data,width,"right"))
+ else
+ insert_node_after(list,tail,linefiller(current,data,width,"right"))
+ if distance > 0 then
+ insert_node_after(list,tail,new_kern(distance))
end
end
end
@@ -708,3 +744,35 @@ implement {
onlyonce = true,
actions = nodes.linefillers.enable
}
+
+-- We add a bonus feature here:
+
+interfaces.implement {
+ name = "autorule",
+ arguments = {
+ {
+ { "width", "dimension" },
+ { "height", "dimension" },
+ { "depth", "dimension" },
+ { "left", "dimension" },
+ { "right", "dimension" },
+ },
+ },
+ actions = function(t)
+ local l = t.left
+ local r = t.right
+ local n = new_rule(
+ t.width,
+ t.height,
+ t.depth
+ )
+ setattrlist(n,true)
+ if l then
+ setfield(n,"left",l)
+ end
+ if r then
+ setfield(n,"right",r)
+ end
+ context(tonode(n))
+ end
+}
diff --git a/tex/context/base/mkiv/node-rul.mkiv b/tex/context/base/mkiv/node-rul.mkiv
index 643e93c42..19f398eb9 100644
--- a/tex/context/base/mkiv/node-rul.mkiv
+++ b/tex/context/base/mkiv/node-rul.mkiv
@@ -71,7 +71,7 @@
%definesystemattribute[ruled]
%definesystemattribute[shifted]
-\registerctxluafile{node-rul}{}
+\registerctxluafile{node-rul}{optimize}
\installcorenamespace{bar}
\installcorenamespace{barindex}
@@ -146,6 +146,8 @@
{\node_rules_set{#1}\barparameter\c!left}%
{\relax\barparameter\c!right}}
+% store in properties
+
\unexpanded\def\node_rules_set#1% maybe reverse the 1000 (also maybe use more attributes instead of settings)
{\edef\currentbar{#1}%
\usebarstyleandcolor\c!foregroundstyle\c!foregroundcolor
@@ -571,4 +573,39 @@
\c!distance=.25\emwidth,
\c!rulethickness=.25\exheight]
+%D Bonus:
+%D
+%D \starttyping
+%D \startuseMPgraphic{foo}
+%D fill unitsquare
+%D xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8)
+%D shifted (-ExHeight/8,ExHeight/16)
+%D withcolor RuleColor ;
+%D \stopuseMPgraphic
+%D
+%D \definelinefiller[foo][mp=foo,color=darkred]
+%D
+%D \linefillerhbox[foo]{OEPS}
+%D \stoptyping
+
+\unexpanded\def\node_backgrounds_filler_box#1#2[#3]%
+ {\bgroup
+ \clf_enablebackgroundboxes
+ \dowithnextbox{%
+ \node_linefiller_set{#3}% already sets the attribute
+ #1%
+ attr \backgroundattribute \plusone
+ % attr \linefillerattribute \the\attribute\linefillerattribute
+ {\box\nextbox}%
+ \egroup}%
+ #2}
+
+\unexpanded\def\linefillerhbox{\node_backgrounds_filler_box\hpack\hbox}
+\unexpanded\def\linefillervbox{\node_backgrounds_filler_box\vpack\vbox}
+\unexpanded\def\linefillervtop{\node_backgrounds_filler_box\tpack\vtop}
+
+%D Bonus:
+
+\unexpanded\def\autorule{\clf_autorule}
+
\protect \endinput
diff --git a/tex/context/base/mkiv/node-scn.lua b/tex/context/base/mkiv/node-scn.lua
index b294b3013..a40a5271a 100644
--- a/tex/context/base/mkiv/node-scn.lua
+++ b/tex/context/base/mkiv/node-scn.lua
@@ -12,8 +12,6 @@ local attributes = attributes
local nodes = nodes
local nuts = nodes.nuts
-local tonode = nuts.tonode
-local tonut = nuts.tonut
local getnext = nuts.getnext
local getprev = nuts.getprev
@@ -26,9 +24,8 @@ local setlist = nuts.setlist
local end_of_math = nuts.end_of_math
local nodecodes = nodes.nodecodes
-local rulecodes = nodes.rulecodes
+local leadercodes = nodes.leadercodes
local gluecodes = nodes.gluecodes
-local listcodes = nodes.listcodes
local kerncodes = nodes.kerncodes
local glyph_code = nodecodes.glyph
@@ -46,7 +43,8 @@ local vlist_code = nodecodes.vlist
local userskip_code = gluecodes.userskip
local spaceskip_code = gluecodes.spaceskip
local xspaceskip_code = gluecodes.xspaceskip
-local leader_code = gluecodes.leaders
+
+local leaders_code = leadercodes.leaders
local fontkern_code = kerncodes.fontkern
@@ -97,7 +95,7 @@ local function striprange(first,last) -- todo: dir
return first, last
end
-nodes.striprange = striprange
+nuts.striprange = striprange
-- todo: order and maybe other dimensions
@@ -205,7 +203,7 @@ local function processwords(attribute,data,flush,head,parent,skip) -- we have hl
elseif id == glue_code then
-- catch \underbar{a} \underbar{a} (subtype test is needed)
local subtype = getsubtype(n)
- if getattr(n,attribute) and (subtype == userskip_code or subtype == spaceskip_code or subtype == xspaceskip_code or (leaders and subtype >= leader_code)) then
+ if getattr(n,attribute) and (subtype == userskip_code or subtype == spaceskip_code or subtype == xspaceskip_code or (leaders and subtype >= leaders_code)) then
l = n
else
head, done = flush(head,f,l,d,level,parent,strip), true
@@ -228,17 +226,11 @@ local function processwords(attribute,data,flush,head,parent,skip) -- we have hl
end
end
-nodes.processwords = function(attribute,data,flush,head,parent) -- we have hlistdir and local dir
- head = tonut(head)
- if parent then
- parent = tonut(parent)
- end
- local head, done = processwords(attribute,data,flush,head,parent)
- return tonode(head), done
+nuts.processwords = function(attribute,data,flush,head,parent) -- we have hlistdir and local dir
+ return processwords(attribute,data,flush,head,parent)
end
-- works on lines !
-
-- todo: stack because skip can change when nested
local function processranges(attribute,flush,head,parent,depth,skip)
@@ -319,11 +311,6 @@ local function processranges(attribute,flush,head,parent,depth,skip)
end
end
-nodes.processranges = function(attribute,flush,head,parent) -- we have hlistdir and local dir
- head = tonut(head)
- if parent then
- parent = tonut(parent)
- end
- local head, done = processranges(attribute,flush,head,parent,0)
- return tonode(head), done
+nuts.processranges = function(attribute,flush,head,parent) -- we have hlistdir and local dir
+ return processranges(attribute,flush,head,parent,0)
end
diff --git a/tex/context/base/mkiv/node-ser.lua b/tex/context/base/mkiv/node-ser.lua
index 7ed2b8d00..6fc2b7ea4 100644
--- a/tex/context/base/mkiv/node-ser.lua
+++ b/tex/context/base/mkiv/node-ser.lua
@@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['node-ser'] = {
-- beware, some field names will change in a next releases
-- of luatex; this is pretty old code that needs an overhaul
-local type = type
+local type, tostring = type, tostring
local concat, tohash, sortedkeys, printtable, serialize = table.concat, table.tohash, table.sortedkeys, table.print, table.serialize
local formatters, format, rep = string.formatters, string.format, string.rep
@@ -24,16 +24,17 @@ local is_node = nodes.is_node
local nodecodes = nodes.nodecodes
local subtcodes = nodes.codes
-local noadcodes = nodes.noadcodes
local getfields = nodes.fields
local tonode = nodes.tonode
+local tonut = nodes.tonut
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
----- utfchar = utf.char
local f_char = formatters["%U"]
+local f_attr = formatters["<%i>"]
----- fontchars = { } table.setmetatableindex(fontchars,function(t,k) fontchars = fonts.hashes.characters return fontchars[k] end)
----- f_char = utilities.strings.chkuni -- formatters["%!chkuni!"]
@@ -87,7 +88,7 @@ local ignore = allocate ( tohash {
local dimension = allocate ( tohash {
"width", "height", "depth", "shift",
"stretch", "shrink",
- "xoffset", "yoffset", "xadvance",
+ "xoffset", "yoffset",
"surround",
"kern",
"box_left_width", "box_right_width"
@@ -145,6 +146,7 @@ local function totable(n,flat,verbose,noattributes) -- nicest: n,true,true,true
if ignore[v] then
-- skip
elseif noattributes and v == "attr" then
+ tt[v] = f_attr(tonut(nv))
-- skip
elseif v == "prev" then
tt[v] = "<node>"
diff --git a/tex/context/base/mkiv/node-shp.lua b/tex/context/base/mkiv/node-shp.lua
index 2e7a3529a..306e38f6a 100644
--- a/tex/context/base/mkiv/node-shp.lua
+++ b/tex/context/base/mkiv/node-shp.lua
@@ -13,50 +13,51 @@ local format = string.format
local concat, sortedpairs = table.concat, table.sortedpairs
local setmetatableindex = table.setmetatableindex
-local nodecodes = nodes.nodecodes
-local whatsitcodes = nodes.whatsitcodes
-local disccodes = nodes.disccodes
+local nodecodes = nodes.nodecodes
+local whatsitcodes = nodes.whatsitcodes
+local disccodes = nodes.disccodes
-local tasks = nodes.tasks
-local handlers = nodes.handlers
+local tasks = nodes.tasks
+local handlers = nodes.handlers
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local disc_code = nodecodes.disc
-local whatsit_code = nodecodes.whatsit
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local disc_code = nodecodes.disc
+local whatsit_code = nodecodes.whatsit
-local fulldisc_code = disccodes.discretionary
+local discretionarydisc_code = disccodes.discretionary
-local texgetbox = tex.getbox
+local implement = interfaces.implement
-local implement = interfaces.implement
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+local remove_node = nuts.remove
-local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
-local remove_node = nuts.remove
-local traverse_nodes = nuts.traverse
+local nextnode = nuts.traversers.node
-local setfield = nuts.setfield
-local setlink = nuts.setlink
-local setprev = nuts.setprev
-local setnext = nuts.setnext
-local getid = nuts.getid
-local getdisc = nuts.getdisc
-local getboth = nuts.getboth
-local getnext = nuts.getnext
-local getlist = nuts.getlist
-local getsubtype = nuts.getsubtype
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+local setprev = nuts.setprev
+local setnext = nuts.setnext
+local getid = nuts.getid
+local getdisc = nuts.getdisc
+local getboth = nuts.getboth
+local getnext = nuts.getnext
+local getlist = nuts.getlist
+local getsubtype = nuts.getsubtype
-local setlist = nuts.setlist
+local setlist = nuts.setlist
-local removables = {
+local getbox = nuts.getbox
+
+local removables = {
[whatsitcodes.open] = true,
[whatsitcodes.close] = true,
[whatsitcodes.write] = true,
[whatsitcodes.savepos] = true,
[whatsitcodes.latelua] = true,
- [whatsitcodes.pdfdest] = true,
+ -- [whatsitcodes.pdfdest] = true,
}
-- About 10% of the nodes make no sense for the backend. By (at least)
@@ -72,7 +73,7 @@ local function cleanup_redundant(head) -- better name is: flatten_page
while start do
local id = getid(start)
if id == disc_code then
- if getsubtype(start) == fulldisc_code then
+ if getsubtype(start) == discretionarydisc_code then
local _, _, replace, _, _ tail = getdisc(start,true)
if replace then
local prev, next = getboth(start)
@@ -117,6 +118,8 @@ local function cleanup_redundant(head) -- better name is: flatten_page
return head
end
+handlers.cleanuppage = cleanup_redundant -- nut
+
local function cleanup_flushed(head) -- rough
local start = head
while start do
@@ -143,26 +146,20 @@ local function cleanup_flushed(head) -- rough
return head
end
-function handlers.cleanuppage(head)
- return tonode(cleanup_redundant(tonut(head))), true
-end
-
-function handlers.cleanupbox(head)
- return tonode(cleanup_flushed(tonut(head))), true
+function handlers.cleanupbox(box)
+ cleanup_flushed(getbox(box))
end
local actions = tasks.actions("shipouts")
-function handlers.finalize(head,where) -- problem, attr loaded before node, todo ...
- return actions(head,where)
+function handlers.finalizebox(box)
+ actions(getbox(box)) -- nut
end
--- handlers.finalize = actions
-
-- interface
-implement { name = "cleanupbox", actions = { texgetbox, cleanup_flushed }, arguments = "integer" }
-implement { name = "finalizebox", actions = { texgetbox, actions }, arguments = "integer" }
+implement { name = "cleanupbox", actions = handlers.cleanupbox, arguments = "integer" }
+implement { name = "finalizebox", actions = handlers.finalizebox, arguments = "integer" }
-- just in case we want to optimize lookups:
@@ -192,8 +189,7 @@ local function count(head,data,subcategory)
-- no components, pre, post, replace .. can maybe an option .. but
-- we use this for optimization so it makes sense to look the the
-- main node only
- for n in traverse_nodes(tonut(head)) do
- local id = getid(n)
+ for n, id in nextnode, tonut(head) do
local dn = data[nodecodes[id]] -- we could use id and then later convert to nodecodes
dn[subcategory] = dn[subcategory] + 1
if id == hlist_code or id == vlist_code then
diff --git a/tex/context/base/mkiv/node-syn.lua b/tex/context/base/mkiv/node-syn.lua
index 9d716c44a..a00dc65ec 100644
--- a/tex/context/base/mkiv/node-syn.lua
+++ b/tex/context/base/mkiv/node-syn.lua
@@ -24,7 +24,16 @@ if not modules then modules = { } end modules ['node-syn'] = {
-- I only tested SumatraPDF with SciTE, for which one needs to configure in the
-- viewer:
--
--- InverseSearchCmdLine = c:\data\system\scite\wscite\scite.exe "%f" "-goto:%l" $
+-- InverseSearchCmdLine = c:\data\system\scite\wscite\scite.exe "%f" "-goto:%l" $
+--
+-- In fact, a way more powerful implementation would have been not to add a library
+-- to a viewer, but letthe viewer call an external program:
+--
+-- InverseSearchCmdLine = mtxrun.exe --script synctex --edit --name="%f" --line="%l" $
+--
+-- which would (re)launch the editor in the right spot. That way we can really
+-- tune well to the macro package used and also avoid the fuzzy heuristics of
+-- the library.
--
-- Unfortunately syntex always removes the files at the end and not at the start
-- (this happens in synctexterminate) so we need to work around that by using an
@@ -124,10 +133,9 @@ local openfile, renamefile, removefile = io.open, os.rename, os.remove
local report_system = logs.reporter("system")
local tex = tex
+local texget = tex.get
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local getid = nuts.getid
local getlist = nuts.getlist
@@ -168,14 +176,9 @@ local set_synctex_tag = tex.set_synctex_tag
local force_synctex_tag = tex.force_synctex_tag
local force_synctex_line = tex.force_synctex_line
----- get_synctex_tag = tex.get_synctex_tag
------ get_synctex_line = tex.get_synctex_line
+local get_synctex_line = tex.get_synctex_line
local set_synctex_mode = tex.set_synctex_mode
-local getpos = function()
- getpos = backends.codeinjections.getpos
- return getpos()
- end
-
local foundintree = resolvers.foundintree
local eol = "\010"
@@ -199,6 +202,8 @@ local f_vlist_2 = formatters["v%i,%i:%i,%s:%i,%i,%i\010"]
local synctex = luatex.synctex or { }
luatex.synctex = synctex
+local getpos ; getpos = function() getpos = job.positions.getpos return getpos() end
+
-- status stuff
local enabled = false
@@ -268,6 +273,34 @@ function synctex.resetfilename()
end
end
+do
+
+ local nesting = 0
+ local ignored = false
+
+ function synctex.pushline()
+ nesting = nesting + 1
+ if nesting == 1 then
+ local l = get_synctex_line()
+ ignored = l and l > 0
+ if not ignored then
+ force_synctex_line(texget("inputlineno"))
+ end
+ end
+ end
+
+ function synctex.popline()
+ if nesting == 1 then
+ if not ignored then
+ force_synctex_line()
+ ignored = false
+ end
+ end
+ nesting = nesting - 1
+ end
+
+end
+
-- the node stuff
local filehandle = nil
@@ -324,6 +357,7 @@ end
function synctex.wrapup()
if tmpfile then
renamefile(tmpfile,logfile)
+ tmpfile = nil
end
end
@@ -340,9 +374,15 @@ local function flushpostamble()
enabled = false
end
+local getpagedimensions getpagedimensions = function()
+ getpagedimensions = backends.codeinjections.getpagedimensions
+ return getpagedimensions()
+end
+
-- local function doaction(action,t,l,w,h,d)
+-- local pagewidth, pageheight = getpagedimensions()
-- local x, y = getpos()
--- filehandle:write(action(t,l,x,tex.pageheight-y,w,h,d))
+-- filehandle:write(action(t,l,x,pageheight-y,w,h,d))
-- nofobjects = nofobjects + 1
-- end
--
@@ -378,24 +418,27 @@ end
-- generic
--
-- local function doaction(t,l,w,h,d)
+-- local pagewidth, pageheight = getpagedimensions()
-- local x, y = getpos()
--- filehandle:write(f_hlist_1(t,l,x,tex.pageheight-y,w,h,d))
+-- filehandle:write(f_hlist_1(t,l,x,pageheight-y,w,h,d))
-- nofobjects = nofobjects + 1
-- end
local x_hlist do
local function doaction_1(t,l,w,h,d)
+ local pagewidth, pageheight = getpagedimensions()
local x, y = getpos()
- filehandle:write(f_hlist_1(t,l,x,tex.pageheight-y,w,h,d))
+ filehandle:write(f_hlist_1(t,l,x,pageheight-y,w,h,d))
nofobjects = nofobjects + 1
end
-- local lastx, lasty, lastw, lasth, lastd
--
-- local function doaction_2(t,l,w,h,d)
+ -- local pagewidth, pageheight = getpagedimensions()
-- local x, y = getpos()
- -- y = tex.pageheight-y
+ -- y = pageheight-y
-- filehandle:write(f_hlist_2(t,l,
-- x == lastx and "=" or x,
-- y == lasty and "=" or y,
@@ -412,8 +455,9 @@ local x_hlist do
local lasty = false
local function doaction_2(t,l,w,h,d)
+ local pagewidth, pageheight = getpagedimensions()
local x, y = getpos()
- y = tex.pageheight - y
+ y = pageheight - y
filehandle:write(f_hlist_2(t,l,x,y == lasty and "=" or y,w,h,d))
lasty = y
nofobjects = nofobjects + 1
@@ -623,16 +667,10 @@ end
collect = collect_max
function synctex.collect(head,where)
- if enabled then
- if where == "object" then
- return head, false
- else
- local h = tonut(head)
- h = collect(h,h)
- return tonode(h), true
- end
+ if enabled and where ~= "object" then
+ return collect(head,head)
else
- return head, false
+ return head
end
end
@@ -645,10 +683,9 @@ function synctex.start()
writeanchor()
filehandle:write("{",nofsheets,eol)
-- this seems to work:
- local h = tex.pageheight
- local w = tex.pagewidth
+ local pagewidth, pageheight = getpagedimensions()
filehandle:write(z_hlist)
- filehandle:write(f_vlist_1(0,0,0,h,w,h,0))
+ filehandle:write(f_vlist_1(0,0,0,pageheight,pagewidth,pageheight,0))
end
end
end
@@ -678,7 +715,7 @@ function synctex.enable()
enabled = true
set_synctex_mode(3) -- we want details
if not used then
- nodes.tasks.appendaction("shipouts", "after", "luatex.synctex.collect")
+ nodes.tasks.enableaction("shipouts","luatex.synctex.collect")
report_system("synctex functionality is enabled, expect 5-10 pct runtime overhead!")
used = true
end
@@ -786,11 +823,21 @@ implement {
}
implement {
- name = "synctexpause",
- actions = synctex.pause,
+ name = "synctexpause",
+ actions = synctex.pause,
}
implement {
- name = "synctexresume",
- actions = synctex.resume,
+ name = "synctexresume",
+ actions = synctex.resume,
+}
+
+interfaces.implement {
+ name = "synctexpushline",
+ actions = synctex.pushline,
+}
+interfaces.implement {
+ name = "synctexpopline",
+ actions = synctex.popline,
}
+
diff --git a/tex/context/base/mkiv/node-tex.lua b/tex/context/base/mkiv/node-tex.lua
index c9d3091df..5857fd2e6 100644
--- a/tex/context/base/mkiv/node-tex.lua
+++ b/tex/context/base/mkiv/node-tex.lua
@@ -6,33 +6,40 @@ if not modules then modules = { } end modules ['node-tex'] = {
license = "see context related readme files"
}
-builders = builders or { }
-local kernel = builders.kernel or { }
-builders.kernel = kernel
-
-local hyphenate = lang.hyphenate
-local ligaturing = node.ligaturing
-local kerning = node.kerning
-
-kernel.originals = {
- hyphenate = hyphenate,
- ligaturing = ligaturing,
- kerning = kerning,
-}
+builders = builders or { }
+local kernel = builders.kernel or { }
+builders.kernel = kernel
+
+local nuts = nodes.nuts
+
+local hyphenate = lang.hyphenate
+local hyphenating = nuts.hyphenating
+local ligaturing = nuts.ligaturing
+local kerning = nuts.kerning
+local cleanup = nuts.flush_components
function kernel.hyphenation(head)
- local done = hyphenate(head)
- return head, done
+ return (hyphenate(head)) -- nodes !
+end
+
+function kernel.hyphenating(head)
+ return (hyphenating(head))
end
function kernel.ligaturing(head)
- local head, tail, done = ligaturing(head) -- we return 3 values indeed
- return head, done
+ return (ligaturing(head))
end
function kernel.kerning(head)
- local head, tail, done = kerning(head) -- we return 3 values indeed
- return head, done
+ return (kerning(head))
+end
+
+if cleanup then
+
+ function kernel.cleanup(head)
+ return (cleanup(head))
+ end
+
end
callbacks.register('hyphenate' , false, "normal hyphenation routine, called elsewhere")
diff --git a/tex/context/base/mkiv/node-tra.lua b/tex/context/base/mkiv/node-tra.lua
index f12599866..e1b6927fb 100644
--- a/tex/context/base/mkiv/node-tra.lua
+++ b/tex/context/base/mkiv/node-tra.lua
@@ -21,68 +21,67 @@ local report_nodes = logs.reporter("nodes","tracing")
local nodes, node, context = nodes, node, context
-local texgetattribute = tex.getattribute
-
-local tracers = nodes.tracers or { }
-nodes.tracers = tracers
-
-local tasks = nodes.tasks or { }
-nodes.tasks = tasks
-
-local handlers = nodes.handlers or {}
-nodes.handlers = handlers
-
-local injections = nodes.injections or { }
-nodes.injections = injections
-
-local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
-
-local getnext = nuts.getnext
-local getprev = nuts.getprev
-local getid = nuts.getid
-local getchar = nuts.getchar
-local getsubtype = nuts.getsubtype
-local getlist = nuts.getlist
-local getdisc = nuts.getdisc
-local setattr = nuts.setattr
-local getglue = nuts.getglue
-local isglyph = nuts.isglyph
-local getcomponents = nuts.getcomponents
-local getdir = nuts.getdir
-local getwidth = nuts.getwidth
-
-local flush_list = nuts.flush_list
-local count_nodes = nuts.countall
-local used_nodes = nuts.usedlist
-
-local traverse_by_id = nuts.traverse_id
-local traverse_nodes = nuts.traverse
-local d_tostring = nuts.tostring
-
-local nutpool = nuts.pool
-local new_rule = nutpool.rule
-
-local nodecodes = nodes.nodecodes
-local whatcodes = nodes.whatcodes
-local skipcodes = nodes.skipcodes
-local fillcodes = nodes.fillcodes
-
-local glyph_code = nodecodes.glyph
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local disc_code = nodecodes.disc
-local glue_code = nodecodes.glue
-local kern_code = nodecodes.kern
-local rule_code = nodecodes.rule
-local dir_code = nodecodes.dir
-local localpar_code = nodecodes.localpar
-local whatsit_code = nodecodes.whatsit
-
-local dimenfactors = number.dimenfactors
-local fillorders = nodes.fillcodes
-local formatters = string.formatters
+local texgetattribute = tex.getattribute
+
+local tracers = nodes.tracers or { }
+nodes.tracers = tracers
+
+local tasks = nodes.tasks or { }
+nodes.tasks = tasks
+
+local handlers = nodes.handlers or {}
+nodes.handlers = handlers
+
+local injections = nodes.injections or { }
+nodes.injections = injections
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getlist = nuts.getlist
+local getdisc = nuts.getdisc
+local setattr = nuts.setattr
+local getglue = nuts.getglue
+local isglyph = nuts.isglyph
+local getdirection = nuts.getdirection
+local getwidth = nuts.getwidth
+
+local flush_list = nuts.flush_list
+local count_nodes = nuts.countall
+local used_nodes = nuts.usedlist
+
+local nextnode = nuts.traversers.node
+local nextglyph = nuts.traversers.glyph
+
+local d_tostring = nuts.tostring
+
+local nutpool = nuts.pool
+local new_rule = nutpool.rule
+
+local nodecodes = nodes.nodecodes
+local whatsitcodes = nodes.whatsitcodes
+local fillcodes = nodes.fillcodes
+
+local subtypes = nodes.subtypes
+
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local disc_code = nodecodes.disc
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+local rule_code = nodecodes.rule
+local dir_code = nodecodes.dir
+local localpar_code = nodecodes.localpar
+local whatsit_code = nodecodes.whatsit
+
+local dimenfactors = number.dimenfactors
+local formatters = string.formatters
-- this will be reorganized:
@@ -90,23 +89,26 @@ function nodes.showlist(head, message)
if message then
report_nodes(message)
end
- for n in traverse_nodes(tonut(head)) do
+ for n in nextnode, tonut(head) do
report_nodes(d_tostring(n))
end
end
function nodes.handlers.checkglyphs(head,message)
- local h = tonut(head)
+ local h = tonut(head) -- tonut needed?
local t = { }
- for g in traverse_by_id(glyph_code,h) do
- t[#t+1] = formatters["%U:%s"](getchar(g),getsubtype(g))
+ local n = 0
+ local f = formatters["%U:%s"]
+ for g, char, font in nextglyph, h do
+ n = n + 1
+ t[n] = f(char,getsubtype(g))
end
- if #t > 0 then
- if message and message ~= "" then
- report_nodes("%s, %s glyphs: % t",message,#t,t)
- else
- report_nodes("%s glyphs: % t",#t,t)
- end
+ if n == 0 then
+ -- nothing to report
+ elseif message and message ~= "" then
+ report_nodes("%s, %s glyphs: % t",message,n,t)
+ else
+ report_nodes("%s glyphs: % t",n,t)
end
return false
end
@@ -114,8 +116,8 @@ end
function nodes.handlers.checkforleaks(sparse)
local l = { }
local q = used_nodes()
- for p in traverse_nodes(q) do
- local s = table.serialize(nodes.astable(p,sparse),nodecodes[getid(p)])
+ for p, id in nextnode, q do
+ local s = table.serialize(nodes.astable(p,sparse),nodecodes[id])
l[s] = (l[s] or 0) + 1
end
flush_list(q)
@@ -124,42 +126,51 @@ function nodes.handlers.checkforleaks(sparse)
end
end
-local f_sequence = formatters["U+%04X:%s"]
-local f_subrange = formatters["[[ %s ][ %s ][ %s ]]"]
+local fontcharacters -- = fonts.hashes.descriptions
local function tosequence(start,stop,compact)
if start then
+ if not fontcharacters then
+ fontcharacters = fonts.hashes.descriptions
+ if not fontcharacters then
+ return "[no char data]"
+ end
+ end
+ local f_sequence = formatters["U+%04X:%s"]
+ local f_subrange = formatters["[[ %s ][ %s ][ %s ]]"]
start = tonut(start)
stop = stop and tonut(stop)
local t = { }
+ local n = 0
while start do
local c, id = isglyph(start)
if c then
- if compact then
- local components = getcomponents(start)
- if components then
- t[#t+1] = tosequence(components,nil,compact)
- else
- t[#t+1] = utfchar(c)
+ local u = fontcharacters[id][c] -- id == font id
+ u = u and u.unicode or c
+ if type(u) == "table" then
+ local tt = { }
+ for i=1,#u do
+ local c = u[i]
+ tt[i] = compact and utfchar(c) or f_sequence(c,utfchar(c))
end
+ n = n + 1 ; t[n] = "(" .. concat(tt," ") .. ")"
else
- t[#t+1] = f_sequence(c,utfchar(c))
+ n = n + 1 ; t[n] = compact and utfchar(c) or f_sequence(c,utfchar(c))
end
elseif id == disc_code then
local pre, post, replace = getdisc(start)
t[#t+1] = f_subrange(pre and tosequence(pre),post and tosequence(post),replace and tosequence(replace))
elseif id == rule_code then
- if compact then
- t[#t+1] = "|"
- else
- t[#t+1] = nodecodes[id]
- end
- elseif id == dir_code or id == localpar_code then
- t[#t+1] = "[" .. getdir(start) .. "]"
+ n = n + 1 ; t[n] = compact and "|" or nodecodes[id] or "?"
+ elseif id == dir_code then
+ local d, p = getdirection(start)
+ n = n + 1 ; t[n] = "[<" .. (p and "-" or "+") .. d .. ">]" -- todo l2r etc
+ elseif id == localpar_code and getsubtype(start) == 0 then
+ n = n + 1 ; t[n] = "[<" .. getdirection(start) .. ">]" -- todo l2r etc
elseif compact then
- t[#t+1] = "[]"
+ n = n + 1 ; t[n] = "[]"
else
- t[#t+1] = nodecodes[id]
+ n = n + 1 ; t[n] = nodecodes[id]
end
if start == stop then
break
@@ -180,13 +191,13 @@ end
nodes.tosequence = tosequence
nuts .tosequence = tosequence
-function nodes.report(t,done)
- report_nodes("output %a, changed %a, %s nodes",status.output_active,done,count_nodes(tonut(t)))
+function nodes.report(t)
+ report_nodes("output %a, %s nodes",status.output_active,count_nodes(t))
end
function nodes.packlist(head)
local t = { }
- for n in traverse_nodes(tonut(head)) do
+ for n in nextnode, tonut(head) do
t[#t+1] = d_tostring(n)
end
return t
@@ -198,10 +209,11 @@ function nodes.idstostring(head,tail)
local t = { }
local last_id = nil
local last_n = 0
- for n in traverse_nodes(head,tail) do -- hm, does not stop at tail
- local id = getid(n)
+ local f_two = formatters["[%s*%s]"]
+ local f_one = formatters["[%s]"]
+ for n, id, subtype in nextnode, head do
if id == whatsit_code then
- id = whatcodes[getsubtype(n)]
+ id = whatsitcodes[subtype]
else
id = nodecodes[id]
end
@@ -212,9 +224,9 @@ function nodes.idstostring(head,tail)
last_n = last_n + 1
else
if last_n > 1 then
- t[#t+1] = formatters["[%s*%s]"](last_n,last_id)
+ t[#t+1] = f_two(last_n,last_id)
else
- t[#t+1] = formatters["[%s]"](last_id)
+ t[#t+1] = f_one(last_id)
end
last_id = id
last_n = 1
@@ -227,14 +239,29 @@ function nodes.idstostring(head,tail)
t[#t+1] = "no nodes"
else
if last_n > 1 then
- t[#t+1] = formatters["[%s*%s]"](last_n,last_id)
+ t[#t+1] = f_two(last_n,last_id)
else
- t[#t+1] = formatters["[%s]"](last_id)
+ t[#t+1] = f_one(last_id)
end
end
return concat(t," ")
end
+function nodes.idsandsubtypes(head)
+ local h = tonut(head)
+ local t = { }
+ local f = formatters["%s:%s"]
+ for n, id, subtype in nextnode, h do
+ local c = nodecodes[id]
+ if subtype then
+ t[#t+1] = f(c,subtypes[id][subtype])
+ else
+ t[#t+1] = c
+ end
+ end
+ return concat(t, " ")
+end
+
-- function nodes.xidstostring(head,tail) -- only for special tracing of backlinks
-- head = tonut(head)
-- tail = tonut(tail)
@@ -299,17 +326,19 @@ nodes.showsimplelist = function(h,depth) showsimplelist(h,depth,0) end
local function listtoutf(h,joiner,textonly,last,nodisc)
local w = { }
local n = 0
+ local g = formatters["<%i>"]
+ local d = formatters["[%s|%s|%s]"]
while h do
local c, id = isglyph(h)
if c then
- n = n + 1 ; w[n] = c >= 0 and utfchar(c) or formatters["<%i>"](c)
+ n = n + 1 ; w[n] = c >= 0 and utfchar(c) or g(c)
if joiner then
n = n + 1 ; w[n] = joiner
end
elseif id == disc_code then
local pre, pos, rep = getdisc(h)
if not nodisc then
- n = n + 1 ; w[n] = formatters["[%s|%s|%s]"] (
+ n = n + 1 ; w[n] = d(
pre and listtoutf(pre,joiner,textonly) or "",
pos and listtoutf(pos,joiner,textonly) or "",
rep and listtoutf(rep,joiner,textonly) or ""
@@ -354,11 +383,9 @@ local what = { [0] = "unknown", "line", "box", "indent", "row", "cell" }
local function showboxes(n,symbol,depth)
depth = depth or 0
symbol = symbol or "."
- for n in traverse_nodes(tonut(n)) do
- local id = getid(n)
+ for n, id, subtype in nextnode, tonut(n) do
if id == hlist_code or id == vlist_code then
- local s = getsubtype(n)
- report_nodes(rep(symbol,depth) .. what[s] or s)
+ report_nodes(rep(symbol,depth) .. what[subtype] or subtype)
showboxes(getlist(n),symbol,depth+1)
end
end
@@ -401,17 +428,17 @@ local function nodetodimen(n)
width = width / 65536
if stretch_order ~= 0 then
if shrink_order ~= 0 then
- return f_f_f(width,stretch,fillorders[stretch_order],shrink,fillorders[shrink_order])
+ return f_f_f(width,stretch,fillcodes[stretch_order],shrink,fillcodes[shrink_order])
elseif shrink ~= 0 then
- return f_f_m(width,stretch,fillorders[stretch_order],shrink)
+ return f_f_m(width,stretch,fillcodes[stretch_order],shrink)
else
- return f_f_z(width,stretch,fillorders[stretch_order])
+ return f_f_z(width,stretch,fillcodes[stretch_order])
end
elseif shrink_order ~= 0 then
if stretch ~= 0 then
- return f_p_f(width,stretch,shrink,fillorders[shrink_order])
+ return f_p_f(width,stretch,shrink,fillcodes[shrink_order])
else
- return f_z_f(width,shrink,fillorders[shrink_order])
+ return f_z_f(width,shrink,fillcodes[shrink_order])
end
elseif stretch ~= 0 then
if shrink ~= 0 then
@@ -631,6 +658,9 @@ end
tracers.setproperties = setproperties
+-- setting attrlist entries instead of attr for successive entries doesn't
+-- speed up much (this function is only used in tracers anyway)
+
function tracers.setlist(n,c,s)
local nn = tonut(n)
local mc = m_color[c]
diff --git a/tex/context/base/mkiv/node-tsk.lua b/tex/context/base/mkiv/node-tsk.lua
index 1ce7ab1dc..0378c14c6 100644
--- a/tex/context/base/mkiv/node-tsk.lua
+++ b/tex/context/base/mkiv/node-tsk.lua
@@ -52,19 +52,21 @@ end
function tasks.new(specification) -- was: name,arguments,list
local name = specification.name
- local arguments = specification.arguments or 0
local sequence = specification.sequence
if name and sequence then
local tasklist = newsequencer {
+ name = name
-- we can move more to the sequencer now .. todo
}
tasksdata[name] = {
+ name = name,
list = tasklist,
runner = false,
- arguments = arguments,
- -- sequence = sequence,
frozen = { },
- processor = specification.processor or nodeprocessor
+ processor = specification.processor or nodeprocessor,
+ -- could be metatable but best freeze it
+ arguments = specification.arguments or 0,
+ templates = specification.templates,
}
for l=1,#sequence do
appendgroup(tasklist,sequence[l])
@@ -170,18 +172,26 @@ function tasks.disablegroup(name,group)
end
end
-function tasks.appendaction(name,group,action,where,kind)
+function tasks.appendaction(name,group,action,where,kind,state)
local data = validgroup(name,"append action")
if data then
- appendaction(data.list,group,action,where,kind)
+ local list = data.list
+ appendaction(list,group,action,where,kind)
+ if state == "disabled" or (state == "production" and environment.initex) then
+ disableaction(list,action)
+ end
data.runner = false
end
end
-function tasks.prependaction(name,group,action,where,kind)
+function tasks.prependaction(name,group,action,where,kind,state)
local data = validgroup(name,"prepend action")
if data then
- prependaction(data.list,group,action,where,kind)
+ local list = data.list
+ prependaction(list,group,action,where,kind)
+ if state == "disabled" or (state == "production" and environment.initex) then
+ disableaction(list,action)
+ end
data.runner = false
end
end
@@ -216,112 +226,29 @@ statistics.register("node list callback tasks", function()
end
end)
-function tasks.actions(name) -- we optimize for the number or arguments (no ...)
+local function create(data,t)
+ created = created + 1
+ local runner = compile(data.list,data.processor,t)
+ if trace_tasks then
+ report_tasks("creating runner %a, %i actions enabled",t.name,data.list.steps or 0)
+ end
+ data.runner = runner
+ return runner
+end
+
+function tasks.actions(name)
local data = tasksdata[name]
if data then
- local n = data.arguments or 0
- if n == 0 then
- return function(head)
- total = total + 1 -- will go away
- local runner = data.runner
- if not runner then
- created = created + 1
- if trace_tasks then
- report_tasks("creating runner %a",name)
- end
- runner = compile(data.list,data.processor,0)
- data.runner = runner
- end
- return runner(head)
- end
- elseif n == 1 then
- return function(head,one)
- total = total + 1 -- will go away
- local runner = data.runner
- if not runner then
- created = created + 1
- if trace_tasks then
- report_tasks("creating runner %a with %s extra arguments",name,1)
- end
- runner = compile(data.list,data.processor,1)
- data.runner = runner
- end
- return runner(head,one)
- end
- elseif n == 2 then
- return function(head,one,two)
- total = total + 1 -- will go away
- local runner = data.runner
- if not runner then
- created = created + 1
- if trace_tasks then
- report_tasks("creating runner %a with %s extra arguments",name,2)
- end
- runner = compile(data.list,data.processor,2)
- data.runner = runner
- end
- return runner(head,one,two)
- end
- elseif n == 3 then
- return function(head,one,two,three)
- total = total + 1 -- will go away
- local runner = data.runner
- if not runner then
- created = created + 1
- if trace_tasks then
- report_tasks("creating runner %a with %s extra arguments",name,3)
- end
- runner = compile(data.list,data.processor,3)
- data.runner = runner
- end
- return runner(head,one,two,three)
- end
- elseif n == 4 then
- return function(head,one,two,three,four)
- total = total + 1 -- will go away
- local runner = data.runner
- if not runner then
- created = created + 1
- if trace_tasks then
- report_tasks("creating runner %a with %s extra arguments",name,4)
- end
- runner = compile(data.list,data.processor,4)
- data.runner = runner
- end
- return runner(head,one,two,three,four)
- end
- elseif n == 5 then
- return function(head,one,two,three,four,five)
- total = total + 1 -- will go away
- local runner = data.runner
- if not runner then
- created = created + 1
- if trace_tasks then
- report_tasks("creating runner %a with %s extra arguments",name,5)
- end
- runner = compile(data.list,data.processor,5)
- data.runner = runner
- end
- return runner(head,one,two,three,four,five)
- end
- else
- return function(head,...)
- total = total + 1 -- will go away
- local runner = data.runner
- if not runner then
- created = created + 1
- if trace_tasks then
- report_tasks("creating runner %a with %s extra arguments",name,n)
- end
- runner = compile(data.list,data.processor,"n")
- data.runner = runner
- end
- return runner(head,...)
+ local t = data.templates
+ if t then
+ t.name = data.name
+ return function(...)
+ total = total + 1
+ return (data.runner or create(data,t))(...)
end
end
- else
- return nil
end
+ return nil
end
function tasks.table(name) --maybe move this to task-deb.lua
@@ -351,12 +278,132 @@ function tasks.table(name) --maybe move this to task-deb.lua
end
end
--- this will move
+-- -- shipouts everypar -- --
+
+-- the shipout handlers acts on boxes so we don't need to return something
+-- and also don't need to keep the state (done)
+
+local templates = {
+
+default = [[
+return function(head)
+ return head
+end
+]],
+
+process = [[
+local tonut = nodes.tonut
+local tonode = nodes.nuts.tonode
+
+%localize%
+
+return function(head)
+ local nuthead = tonut(head)
+
+%actions%
+ return tonode(nuthead)
+end
+]],
+
+step = [[
+ nuthead = tonut((%action%(tonode(nuthead))))
+]],
+
+nut = [[
+ nuthead = %action%(nuthead)
+]],
+
+nohead = [[
+ %action%(tonode(nuthead))
+]],
+
+nonut = [[
+ %action%(nuthead)
+]],
+
+}
+
+tasks.new {
+ name = "shipouts",
+ processor = nodeprocessor,
+ sequence = {
+ "before", -- users
+ "normalizers", -- system
+ "finishers", -- system
+ "after", -- users
+ "wrapup", -- system
+ },
+ templates = templates
+}
+
+tasks.new {
+ name = "everypar",
+ processor = nodeprocessor,
+ sequence = {
+ "before", -- users
+ "normalizers", -- system
+ "after", -- users
+ },
+ templates = templates,
+}
+
+-- -- finalizers -- --
+
+tasks.new {
+ name = "finalizers",
+ sequence = {
+ "before", -- for users
+ "normalizers",
+ "fonts",
+ "lists",
+ "after", -- for users
+ },
+ processor = nodeprocessor,
+ templates = {
+
+default = [[
+return function(head)
+ return head
+end
+]],
+
+process = [[
+local tonut = nodes.tonut
+local tonode = nodes.nuts.tonode
+
+%localize%
+
+return function(head,groupcode)
+ local nuthead = tonut(head)
+
+%actions%
+ return tonode(nuthead)
+end
+]],
+
+step = [[
+ nuthead = tonut((%action%(tonode(nuthead),groupcode)))
+]],
+
+nut = [[
+ nuthead = %action%(nuthead,groupcode)
+]],
+
+nohead = [[
+ %action%(tonode(nuthead),groupcode)
+]],
+
+nonut = [[
+ %action%(nuthead,groupcode)
+]],
+
+ }
+}
+
+-- -- processors -- --
tasks.new {
name = "processors",
- arguments = 5, -- often only the first is used, and the last three are only passed in hpack filter
--- arguments = 2,
processor = nodeprocessor,
sequence = {
"before", -- for users
@@ -366,56 +413,297 @@ tasks.new {
"fonts",
"lists",
"after", -- for users
+ },
+ templates = {
+
+default = [[
+return function(head)
+ return head
+end
+]],
+
+process = [[
+local tonut = nodes.tonut
+local tonode = nodes.nuts.tonode
+
+%localize%
+
+return function(head,groupcode,size,packtype,direction,attributes)
+ local nuthead = tonut(head)
+
+%actions%
+ return tonode(nuthead)
+end
+]],
+
+step = [[
+ nuthead = tonut((%action%(tonode(nuthead),groupcode,size,packtype,direction,attributes)))
+]],
+
+nut = [[
+ nuthead = %action%(nuthead,groupcode,size,packtype,direction,attributes)
+]],
+
+nohead = [[
+ %action%(tonode(nuthead),groupcode,size,packtype,direction,attributes)
+]],
+
+nonut = [[
+ %action%(nuthead,groupcode,size,packtype,direction,attributes)
+]],
+
}
}
tasks.new {
name = "finalizers",
- arguments = 1,
processor = nodeprocessor,
sequence = {
"before", -- for users
"normalizers",
--- "characters",
--- "finishers",
"fonts",
"lists",
"after", -- for users
+ },
+ templates = {
+
+default = [[
+return function(head)
+ return head
+end
+]],
+
+process = [[
+local tonut = nodes.tonut
+local tonode = nodes.nuts.tonode
+
+%localize%
+
+return function(head)
+ local nuthead = tonut(head)
+
+%actions%
+ return tonode(nuthead)
+end
+]],
+
+step = [[
+ nuthead = tonut((%action%(tonode(nuthead))))
+]],
+
+nut = [[
+ nuthead = %action%(nuthead)
+]],
+
+nohead = [[
+ %action%(tonode(nuthead))
+]],
+
+nonut = [[
+ %action%(nuthead)
+]],
+
}
}
tasks.new {
- name = "shipouts",
- arguments = 1,
- -- nostate = true, -- maybe but only for main ones so little gain
+ name = "mvlbuilders",
processor = nodeprocessor,
sequence = {
"before", -- for users
"normalizers",
- "finishers",
"after", -- for users
+ },
+ templates = {
+
+default = [[
+return function(head)
+ return head
+end
+]],
+
+process = [[
+local tonut = nodes.tonut
+local tonode = nodes.nuts.tonode
+
+%localize%
+
+return function(head,groupcode)
+ local nuthead = tonut(head)
+
+%actions%
+ return tonode(nuthead)
+end
+]],
+
+step = [[
+ nuthead = tonut((%action%(tonode(nuthead),groupcode)))
+]],
+
+nut = [[
+ nuthead = %action%(nuthead,groupcode)
+]],
+
+nohead = [[
+ %action%(tonode(nuthead),groupcode)
+]],
+
+nonut = [[
+ %action%(nuthead,groupcode)
+]],
+
}
}
tasks.new {
- name = "mvlbuilders",
- arguments = 1,
+ name = "vboxbuilders",
processor = nodeprocessor,
sequence = {
"before", -- for users
"normalizers",
"after", -- for users
+ },
+ templates = {
+
+default = [[
+return function(head)
+ return head
+end
+]],
+
+process = [[
+local tonut = nodes.tonut
+local tonode = nodes.nuts.tonode
+
+%localize%
+
+return function(head,groupcode,size,packtype,maxdepth,direction)
+ local nuthead = tonut(head)
+
+%actions%
+ return tonode(nuthead)
+end
+]],
+
+step = [[
+ nuthead = tonut((%action%(tonode(nuthead),groupcode,size,packtype,maxdepth,direction)))
+]],
+
+nut = [[
+ nuthead = %action%(nuthead,groupcode,size,packtype,maxdepth,direction)
+]],
+
+nohead = [[
+ %action%(tonode(nuthead),groupcode,size,packtype,maxdepth,direction)
+]],
+
+nonut = [[
+ %action%(nuthead,groupcode,size,packtype,maxdepth,direction)
+]],
+
}
+
}
tasks.new {
- name = "vboxbuilders",
- arguments = 5,
+ name = "contributers",
processor = nodeprocessor,
sequence = {
"before", -- for users
"normalizers",
"after", -- for users
+ },
+ templates = {
+
+default = [[
+return function(head)
+ return head
+end
+]],
+
+process = [[
+local tonut = nodes.tonut
+local tonode = nodes.nuts.tonode
+
+%localize%
+
+return function(head,groupcode,line)
+ local nuthead = tonut(head)
+ local nutline = tonut(line)
+
+%actions%
+ return tonode(nuthead)
+end
+]],
+
+step = [[
+ nuthead = tonut((%action%(tonode(nuthead),groupcode,line)))
+]],
+
+nut = [[
+ nuthead = %action%(nuthead,groupcode,nutline)
+]],
+
+nohead = [[
+ %action%(tonode(nuthead),groupcode,line)
+]],
+
+nonut = [[
+ %action%(nuthead,groupcode,nutline)
+]],
+
+ }
+}
+
+-- -- math -- --
+
+tasks.new {
+ name = "math",
+ processor = nodeprocessor,
+ sequence = {
+ "before",
+ "normalizers",
+ "builders",
+ "after",
+ },
+ templates = {
+
+default = [[
+return function(head)
+ return head
+end
+]],
+
+process = [[
+local tonut = nodes.tonut
+local tonode = nodes.nuts.tonode
+
+%localize%
+
+return function(head,style,penalties)
+ local nuthead = tonut(head)
+
+%actions%
+ return tonode(nuthead)
+end
+]],
+
+step = [[
+ nuthead = tonut((%action%(tonode(nuthead),style,penalties)))
+]],
+
+nut = [[
+ nuthead = %action%(nuthead,style,penalties)
+]],
+
+nohead = [[
+ %action%(tonode(nuthead),style,penalties)
+]],
+
+nonut = [[
+ %action%(nuthead,style,penalties)
+]],
+
}
}
@@ -441,14 +729,69 @@ tasks.new {
-- }
-- }
-tasks.new {
- name = "contributers",
- arguments = 2, -- [head] where parent
- processor = nodeprocessor,
- sequence = {
- "before", -- for users
- "normalizers",
- "after", -- for users
- }
-}
+-- for now quite useless (too fuzzy)
+--
+-- tasks.new {
+-- name = "listbuilders",
+-- processor = nodeprocessor,
+-- sequence = {
+-- "before", -- for users
+-- "normalizers",
+-- "after", -- for users
+-- },
+-- templates = {
+-- -- we don't need a default
+-- default = [[
+-- return function(box,location,prevdepth)
+-- return box, prevdepth
+-- end
+-- ]],
+-- process = [[
+-- %localize%
+-- return function(box,location,prevdepth,mirrored)
+-- %actions%
+-- return box, prevdepth
+-- end
+-- ]],
+-- step = [[
+-- box, prevdepth = %action%(box,location,prevdepth,mirrored)
+-- ]],
+-- },
+-- }
+
+-- -- math -- --
+
+-- not really a node processor
+-- tasks.new {
+-- name = "newpar",
+-- processor = nodeprocessor,
+-- sequence = {
+-- "before",
+-- "normalizers",
+-- "after",
+-- },
+-- templates = {
+--
+-- default = [[
+-- return function(mode,indent)
+-- return indent
+-- end
+-- ]],
+--
+-- process = [[
+-- %localize%
+--
+-- return function(mode,indent)
+--
+-- %actions%
+-- return indent
+-- end
+-- ]],
+--
+-- step = [[
+-- indent = %action%(mode,indent)
+-- ]],
+--
+-- }
+-- }
diff --git a/tex/context/base/mkiv/node-tst.lua b/tex/context/base/mkiv/node-tst.lua
index 7ad35bd71..0dacff375 100644
--- a/tex/context/base/mkiv/node-tst.lua
+++ b/tex/context/base/mkiv/node-tst.lua
@@ -10,7 +10,7 @@ local nodes, node = nodes, node
local chardata = characters.data
local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
+local gluecodes = nodes.gluecodes
local glue_code = nodecodes.glue
local penalty_code = nodecodes.penalty
@@ -19,10 +19,10 @@ local glyph_code = nodecodes.glyph
local whatsit_code = nodecodes.whatsit
local hlist_code = nodecodes.hlist
-local leftskip_code = skipcodes.leftskip
-local rightskip_code = skipcodes.rightskip
-local abovedisplayshortskip_code = skipcodes.abovedisplayshortskip
-local belowdisplayshortskip_code = skipcodes.belowdisplayshortskip
+local leftskip_code = gluecodes.leftskip
+local rightskip_code = gluecodes.rightskip
+local abovedisplayshortskip_code = gluecodes.abovedisplayshortskip
+local belowdisplayshortskip_code = gluecodes.belowdisplayshortskip
local nuts = nodes.nuts
diff --git a/tex/context/base/mkiv/pack-bar.mkiv b/tex/context/base/mkiv/pack-bar.mkiv
index 06eeebd14..b67d6f14b 100644
--- a/tex/context/base/mkiv/pack-bar.mkiv
+++ b/tex/context/base/mkiv/pack-bar.mkiv
@@ -72,16 +72,16 @@
\vskip\zeropoint\s!plus-\positionbarparameter\c!n \s!fill}}
\unexpanded\def\horizontalgrowingbar[#1]%
- {\hbox to \hsize
+ {\hpack to \hsize
{\setuppositionbar[#1]%
\usepositionbarstyleandcolor\c!style\c!color
- \leaders\vrule\hskip\zeropoint\s!plus \numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill
+ \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}}
\unexpanded\def\verticalgrowingbar[#1]%
- {\vbox to \vsize
+ {\vpack to \vsize
{\setuppositionbar[#1]%
\usepositionbarstyleandcolor\c!style\c!color
\leaders\hrule\vskip\zeropoint\s!plus\numexpr\positionbarparameter\c!n-\positionbarparameter\c!min+\plusone\relax\s!fill
diff --git a/tex/context/base/mkiv/pack-bck.mkvi b/tex/context/base/mkiv/pack-bck.mkvi
index 346e7df57..9f9d843ce 100644
--- a/tex/context/base/mkiv/pack-bck.mkvi
+++ b/tex/context/base/mkiv/pack-bck.mkvi
@@ -245,18 +245,42 @@
%D \macros
%D {backgroundline}
-\unexpanded\def\backgroundline[#color]%
- {\dontleavehmode
- \dowithnextbox{\pack_backgrounds_add_to_nextbox{#color}}\hbox}
+% \unexpanded\def\backgroundline[#color]%
+% {\dontleavehmode
+% \dowithnextbox{\pack_backgrounds_add_to_nextbox{#color}}\hbox}
+%
+% \unexpanded\def\pack_backgrounds_add_to_nextbox#color% handy helper
+% {\hpack
+% {\dousecolorparameter{#color}%
+% \vrule
+% \??width \nextboxwd
+% \??height\nextboxht
+% \??depth \nextboxdp
+% \hskip-\nextboxwd
+% \flushnextbox}}
+
+%D We implement this elsewhere avoiding the rule.
-\unexpanded\def\pack_backgrounds_add_to_nextbox#color% handy helper
- {\hbox
- {\dousecolorparameter{#color}%
- \vrule
- \!!width \nextboxwd
- \!!height\nextboxht
- \!!depth \nextboxdp
- \hskip-\nextboxwd
- \flushnextbox}}
+% \unexpanded\def\backgroundline
+% {\dontleavehmode
+% \pack_backgrounds_add_to_nextbox\hbox\hpack}
+%
+% \unexpanded\def\pack_backgrounds_add_to_nextbox#box#pack[#color]%
+% {\dontleavehmode
+% \dowithnextbox{\pack_backgrounds_add_to_nextbox_indeed#pack{#color}}#box}
+%
+% \unexpanded\def\pack_backgrounds_add_to_nextbox_indeed#pack#color% handy helper
+% {#pack%
+% {\dousecolorparameter{#color}%
+% \vrule
+% \??width \nextboxwd
+% \??height\nextboxht
+% \??depth \nextboxdp
+% \hskip-\nextboxwd
+% \flushnextbox}}
+%
+% \unexpanded\def\backgroundhbox{\pack_backgrounds_add_to_nextbox\hbox\hpack}
+% \unexpanded\def\backgroundvtop{\pack_backgrounds_add_to_nextbox\vtop\tpack}
+% \unexpanded\def\backgroundvbox{\pack_backgrounds_add_to_nextbox\vbox\vpack}
\protect \endinput
diff --git a/tex/context/base/mkiv/pack-box.mkiv b/tex/context/base/mkiv/pack-box.mkiv
index c53b4520c..bf6d4662d 100644
--- a/tex/context/base/mkiv/pack-box.mkiv
+++ b/tex/context/base/mkiv/pack-box.mkiv
@@ -108,6 +108,7 @@
{\global\advance\c_pack_anchors_n\plusone
\pagereference[\v!layer:\v!anchor:\number\c_pack_anchors_n]%
\putboxincache\v!anchor{\number\c_pack_anchors_n}\b_pack_anchors
+% \xtoksapp\t_pack_anchors_flush{\pack_anchors_flush{\number\c_pack_anchors_n}{#1}{#2}}%
\doglobal\appendetoks
\pack_anchors_flush{\number\c_pack_anchors_n}{#1}{#2}%
\to \t_pack_anchors_flush
diff --git a/tex/context/base/mkiv/pack-com.mkiv b/tex/context/base/mkiv/pack-com.mkiv
index 59354208e..1c6f2de73 100644
--- a/tex/context/base/mkiv/pack-com.mkiv
+++ b/tex/context/base/mkiv/pack-com.mkiv
@@ -73,7 +73,7 @@
\newsystemmode{combination}
\appendtoks
- \global\resetsystemmode{combination}%
+ \globalresetsystemmode{combination}%
\to \everyinsidefloat
\newcount\c_pack_combinations_nesting % local
@@ -113,7 +113,7 @@
\setbox\b_pack_combinations_content_saved \box\b_pack_combinations_content
\setbox\b_pack_combinations_caption_saved \box\b_pack_combinations_caption
\else
- \global\setsystemmode{combination}% why global
+ \globalsetsystemmode{combination}% why global
\fi}
\def\pack_combinations_pop
@@ -126,7 +126,7 @@
\setbox\b_pack_combinations_content \box\b_pack_combinations_content_saved
\setbox\b_pack_combinations_caption \box\b_pack_combinations_caption_saved
\else
- \global\resetsystemmode{combination}% why global
+ \globalresetsystemmode{combination}% why global
\fi
\advance\c_pack_combinations_nesting\minusone}
@@ -205,7 +205,7 @@
% {\bgroup
% \scratchtoks{{}}%
% \dorecurse\c_pack_combinations_y
-% {\scratchtoks\expandafter{\the\scratchtoks{}{}}}%
+% {\toksapp{{}{}}}%
% \expandafter\egroup\the\scratchtoks
% \egroup
% \dostoptagged
@@ -290,7 +290,7 @@
\alignmark\alignmark
\m_pack_combinations_rightfiller
\aligntab
- \tabskip\zeropoint \s!plus 1fill
+ \tabskip\zeropoint \s!plus 1fill % \fillskip
\alignmark\alignmark
\cr
\pack_combinations_pickup}
@@ -437,10 +437,10 @@
\nointerlineskip % indeed
\combinationparameter\c!inbetween
\global\c_pack_combinations_x\c_pack_combinations_max
- \globallet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_yes
+ \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_yes
\else
\global\setbox\b_pack_combinations_captions\emptybox
- \globallet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_nop
+ \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_nop
\fi}%
\pack_combinations_flush_captions_indeed
\crcr}
@@ -656,7 +656,7 @@
\newsystemmode{pairedbox}
\appendtoks
- \global\resetsystemmode{pairedbox}%
+ \globalresetsystemmode{pairedbox}%
\to \everyinsidefloat
\installcorenamespace {pairedbox}
@@ -720,7 +720,7 @@
\let\startcaption\pack_common_caption_start
\let\stopcaption \pack_common_caption_stop
%
- \global\setsystemmode{pairedbox}%
+ \globalsetsystemmode{pairedbox}%
\pack_pairedboxes_before
\assumelongusagecs\pack_pairedboxes_first_pickup}
diff --git a/tex/context/base/mkiv/pack-cut.mkiv b/tex/context/base/mkiv/pack-cut.mkiv
index ffd0251d5..84c14d648 100644
--- a/tex/context/base/mkiv/pack-cut.mkiv
+++ b/tex/context/base/mkiv/pack-cut.mkiv
@@ -65,85 +65,87 @@
\def\cutmarkrulethickness{\onepoint}
\unexpanded\def\horizontalcuts
- {\normalhbox to \d_pack_cutmarks_width
- {\dorecurse\horizontalcutmarks{\vrule\s!width\cutmarkrulethickness\s!height\cutmarklength\normalhfill}%
+ {\hpack to \d_pack_cutmarks_width
+ {\dorecurse\horizontalcutmarks{\vrule\s!width\cutmarkrulethickness\s!height\cutmarklength\hfill}%
\unskip}}
\unexpanded\def\verticalcuts
- {\normalvbox to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax
+ {\vpack to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax
{\hsize\cutmarklength
- \dorecurse\verticalcutmarks{\vrule\s!height\cutmarkrulethickness\s!width\hsize\normalvfill}%
+ \dorecurse\verticalcutmarks{\vrule\s!height\cutmarkrulethickness\s!width\hsize\vfill}%
\unskip}}
\unexpanded\def\baselinecuts
{\ifdim\d_pack_cutmarks_depth>\zeropoint
- \normalvbox to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax
+ \vpack to \dimexpr\d_pack_cutmarks_height+\d_pack_cutmarks_depth\relax
{\hsize\dimexpr\cutmarklength/2\relax
- \normalvskip\zeropoint\s!plus\d_pack_cutmarks_height
+ \vskip\zeropoint\s!plus\d_pack_cutmarks_height
\vrule\s!height\cutmarkrulethickness\s!width\hsize
- \normalvskip\zeropoint\s!plus\d_pack_cutmarks_depth}%
+ \vskip\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
+ {\hpack to \d_pack_cutmarks_width
+ {\setbox\scratchbox\hbox to \cutmarklength
+ {\hss\infofont\cutmarksymbol\hss}%
+ \hss
+ \vpack to \cutmarklength
{\scratchdimen\dimexpr\cutmarklength/2\relax
\scratchskip \ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi
- \normalvss
- \hpack 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}}
+ \vss
+ \hbox to \d_pack_cutmarks_width
+ {\llap{\copy\scratchbox\hskip\scratchskip}%
+ \hskip\scratchdimen\hss
+ \infofont#1%
+ \hss\hskip\scratchdimen
+ \rlap{\hskip\scratchskip\copy\scratchbox}}%
+ \vss}%
+ \hss}}
\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
+ \setbox#1\hpack
{\dontcomplain
\forgetall
\boxmaxdepth\maxdimen
\offinterlineskip
\scratchdimen\dimexpr\cutmarklength/2\relax
\hsize\d_pack_cutmarks_width
- \setbox\scratchbox\normalvbox
- {\setbox\scratchbox\normalhbox{\horizontalcuts}%
+ \setbox\scratchbox\vpack
+ {\setbox\scratchbox\hpack{\horizontalcuts}%
\scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi
- \tlap{\copy\scratchbox\normalvskip\scratchskip}%
+ \tlap{\copy\scratchbox\vskip\scratchskip}%
\hpack to \d_pack_cutmarks_width
{\scratchskip\ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi
- \setbox\scratchbox\normalhbox{\verticalcuts}%
- \llap{\copy\scratchbox\normalhskip\scratchskip}%
+ \setbox\scratchbox\hpack{\verticalcuts}%
+ \llap{\copy\scratchbox\hskip\scratchskip}%
\ifdim\d_pack_cutmarks_depth=\zeropoint
- \normalhfill
+ \hfill
\else
\bgroup
- \setbox\scratchbox\normalhbox{\baselinecuts}%
- \llap{\copy\scratchbox\normalhskip\scratchskip}%
- \normalhfill
- \rlap{\normalhskip\scratchskip\copy\scratchbox}%
+ \setbox\scratchbox\hpack{\baselinecuts}%
+ \llap{\copy\scratchbox\hskip\scratchskip}%
+ \hfill
+ \rlap{\hskip\scratchskip\copy\scratchbox}%
\egroup
\fi
- \rlap{\normalhskip\scratchskip\copy\scratchbox}}%
- \blap{\normalvskip\scratchskip\copy\scratchbox}}%
+ \rlap{\hskip\scratchskip\copy\scratchbox}}%
+ \blap{\vskip\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
+ \setbox\scratchbox\vpack
{\scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi
\vskip-\dimexpr\scratchskip+\cutmarklength\relax
- \normalhbox{\cutmarksymbols\cutmarktoptext}%
+ \hpack{\cutmarksymbols\cutmarktoptext}%
\vskip\dimexpr\scratchskip+\d_pack_cutmarks_height+\d_pack_cutmarks_depth+\scratchskip\relax
- \normalhbox{\cutmarksymbols\cutmarkbottomtext}}%
+ \hpack{\cutmarksymbols\cutmarkbottomtext}}%
\ht\scratchbox\d_pack_cutmarks_height
\dp\scratchbox\d_pack_cutmarks_depth
\wd\scratchbox\zeropoint
@@ -156,8 +158,8 @@
\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}
+\unexpanded\def\cuthbox{\hpack\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\hbox}
+\unexpanded\def\cutvbox{\vpack\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\vbox}
+\unexpanded\def\cutvtop{\tpack\bgroup\dowithnextbox{\makecutbox\nextbox\flushnextbox\egroup}\vtop}
\protect \endinput
diff --git a/tex/context/base/mkiv/pack-lyr.mkiv b/tex/context/base/mkiv/pack-lyr.mkiv
index 8661fe57a..e7070cfde 100644
--- a/tex/context/base/mkiv/pack-lyr.mkiv
+++ b/tex/context/base/mkiv/pack-lyr.mkiv
@@ -293,8 +293,8 @@
{\setbox\b_layers\emptybox
\d_pack_layers_x_position\p_pack_layers_sx\dimexpr\p_pack_layers_x\relax
\d_pack_layers_y_position\p_pack_layers_sy\dimexpr\p_pack_layers_y\relax
- \globallet\lastlayerxpos\!!zeropoint
- \globallet\lastlayerypos\!!zeropoint
+ \glet\lastlayerxpos\!!zeropoint
+ \glet\lastlayerypos\!!zeropoint
\doifinset\v!bottom\p_pack_layers_corner\pack_layers_set_bottom_positions
\doifinset\v!right \p_pack_layers_corner\pack_layers_set_right_positions
\doifinset\v!middle\p_pack_layers_corner\pack_layers_set_middle_positions
@@ -540,24 +540,85 @@
% todo: pass the layer with \lastnamedcs
+% \def\pack_layers_flush_single
+% {\startoverlay
+% {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}%
+% {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\fi}%
+% \stopoverlay}
+%
+% \def\pack_layers_flush_double#1%
+% {\startoverlay
+% {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}%
+% {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount {\currentlayer:\the\realpageno}\fi}%
+% {\ifcsname\??layerbox#1\currentlayer \endcsname\pack_layers_flush_indeed\plusone {#1\currentlayer }\fi}%
+% {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\fi}%
+% \stopoverlay}
+
+% optimized:
+
\def\pack_layers_flush_single
- {\startoverlay
- {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}%
- {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\fi}%
- \stopoverlay}
+ {\ifcsname\??layerbox\currentlayer\endcsname
+ \ifvoid\lastnamedcs
+ \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname
+ \ifvoid\lastnamedcs\else
+ \chardef\b_layer_two\lastnamedcs
+ \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two
+ \fi
+ \fi
+ \else
+ \chardef\b_layer_one\lastnamedcs
+ \ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname
+ \ifvoid\lastnamedcs\else
+ \chardef\b_layer_two\lastnamedcs
+ \startoverlay
+ {\pack_layers_flush_indeed\plusone \currentlayer \b_layer_one}%
+ {\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two}%
+ \stopoverlay
+ \fi
+ \else
+ \pack_layers_flush_indeed\plusone\currentlayer\b_layer_one
+ \fi
+ \fi
+ \else\ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname
+ \ifvoid\lastnamedcs
+ % nothing
+ \else
+ \chardef\b_layer_two\lastnamedcs
+ \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two
+ \fi
+ \fi\fi}
+
+% less optimized:
\def\pack_layers_flush_double#1%
{\startoverlay
- {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}%
- {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount {\currentlayer:\the\realpageno}\fi}%
- {\ifcsname\??layerbox#1\currentlayer \endcsname\pack_layers_flush_indeed\plusone {#1\currentlayer }\fi}%
- {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\fi}%
+ {\ifcsname\??layerbox\currentlayer\endcsname
+ \ifvoid\lastnamedcss\else \chardef\b_layer_two\lastnamedcs
+ \pack_layers_flush_indeed\plusone\currentlayer\b_layer_two
+ \fi
+ \fi}%
+ {\ifcsname\??layerbox\currentlayer:\the\realpageno\endcsname
+ \ifvoid\lastnamedcss\else \chardef\b_layer_two\lastnamedcs
+ \pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\b_layer_two
+ \fi
+ \fi}%
+ {\ifcsname\??layerbox#1\currentlayer\endcsname
+ \ifvoid\lastnamedcss\else \chardef\b_layer_two\lastnamedcs
+ \pack_layers_flush_indeed\plusone{#1\currentlayer}\b_layer_two
+ \fi
+ \fi}%
+ {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname
+ \ifvoid\lastnamedcss\else \chardef\b_layer_two\lastnamedcs
+ \pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\b_layer_two
+ \fi
+ \fi}%
\stopoverlay}
\let\pack_layers_top_fill \relax
\let\pack_layers_bottom_fill\vss
-\def\pack_layers_flush_indeed#1#2% quite core, so optimized
+%def\pack_layers_flush_indeed#1#2%
+\def\pack_layers_flush_indeed#1#2#3%
{\begingroup % already grouped
\offinterlineskip
\edef\p_pack_layers_preset{\layerparameter\c!preset}%
@@ -587,7 +648,8 @@
\fi\fi
\fi
\fi
- \chardef\b_layers\csname\??layerbox#2\endcsname % trick
+ %chardef\b_layers\csname\??layerbox#2\endcsname % trick
+ \let\b_layers#3%
% we need to copy in order to retain the negative offsets for a next
% stage of additions, i.e. llx/lly accumulate in repeat mode and the
% compensation may differ each flush depending on added content
diff --git a/tex/context/base/mkiv/pack-mrl.mkiv b/tex/context/base/mkiv/pack-mrl.mkiv
index 85aa3ad04..665d245b3 100644
--- a/tex/context/base/mkiv/pack-mrl.mkiv
+++ b/tex/context/base/mkiv/pack-mrl.mkiv
@@ -39,7 +39,7 @@
\installsimplecommandhandler \??blackrules {blackrules}
\unexpanded\def\blackrule
- {\hbox\bgroup
+ {\hpack\bgroup
\doifelsenextoptionalcs\pack_black_rule_pickup\pack_black_rule_indeed}
\def\pack_black_rule_pickup[#1]%
@@ -99,7 +99,7 @@
%D would probably have taken more tokens.
\unexpanded\def\blackrules % probably never used
- {\hbox\bgroup
+ {\hpack\bgroup
\doifelsenextoptionalcs\pack_black_rules_pickup\pack_black_rules_indeed}
\def\pack_black_rules_pickup[#1]%
@@ -121,23 +121,25 @@
\fi
\fi
\useblackrulesstyleandcolor\c!style\c!color
- \edef\brule
- {\ifcsname\??blackruletype\directblackrulesparameter\c!type\endcsname
- \lastnamedcs
- \else
- \vrule
- \fi}%
- \dorecurse\scratchcounter % a typical case of where we can use a simple loop
- {\brule
- \s!width \scratchwidth
- \s!height\scratchheight
- \s!depth \scratchdepth
- \ifzeropt\scratchdistance\else
- \hskip\scratchdistance
- \fi}%
+ % a typical case of where we can use a simple loop or even a leaders
+ \dorecurse\scratchcounter\pack_black_rules_step
\unskip
\egroup}
+\def\pack_black_rules_step
+ {\ifcsname\??blackruletype\directblackrulesparameter\c!type\endcsname
+ \lastnamedcs
+ \else
+ \vrule
+ \fi
+ \s!width \scratchwidth
+ \s!height\scratchheight
+ \s!depth \scratchdepth
+ \relax
+ \ifzeropt\scratchdistance\else
+ \hskip\scratchdistance
+ \fi}
+
\installcorenamespace{blackruletype}
\setvalue{\??blackruletype mp}%
@@ -578,7 +580,7 @@
{\page[\v!preference] % interferes
\directtextrulesparameter\c!before\relax
\blank[\v!samepage,\v!nowhite]%
- \pack_textrule_with_text{#1}%
+ \pack_textrule_with_text_yes{#1}%
\blank[\v!samepage,\v!nowhite]%
\directtextrulesparameter\c!inbetween\relax
\endgraf}
@@ -598,9 +600,10 @@
\directtextrulesparameter\c!inbetween\relax
\page[\v!preference]}
-\def\pack_textrule_with_text#1%
- {\bgroup
- \setbox\scratchbox\hbox to \availablehsize
+\def\pack_textrule_with_text_yes#1%
+ {\noindent % this will force side floats to be calculated
+ \bgroup
+ \setbox\scratchbox\hpack to \availablehsize
{\scratchwidth \directtextrulesparameter\c!rulethickness\relax
\scratchheight\dimexpr .5\exheight+.5\scratchwidth\relax
\scratchdepth \dimexpr-.5\exheight+.5\scratchwidth\relax
@@ -611,19 +614,41 @@
#1%
\hskip\leftmargindistance}}
{\color[\directtextrulesparameter\c!rulecolor]
- {\vrule\s!height\scratchheight\s!depth\scratchdepth\s!width\directtextrulesparameter\c!width}%
+ {\vrule
+ \s!height\scratchheight
+ \s!depth \scratchdepth
+ \s!width \directtextrulesparameter\c!width}%
\hbox spread 2\dimexpr\directtextrulesparameter\c!distance\relax
{\hss
\usetextrulesstyleandcolor\c!style\c!color
\strut#1%
\hss}}}%
\color[\directtextrulesparameter\c!rulecolor]
- {\leaders\hrule\s!height\scratchheight\s!depth\scratchdepth\hfill}}%
+ {\leaders\hrule
+ \s!height\scratchheight
+ \s!depth \scratchdepth
+ \hfill}}%
\ht\scratchbox\strutht
\dp\scratchbox\strutdp
- \noindent\box\scratchbox
+ \box\scratchbox
+ %\carryoverpar
\egroup}
+\def\pack_textrule_with_text_nop#1%
+ {\ifhmode
+ \endgraf
+ \fi
+ \doifelse{\directtextrulesparameter\c!depthcorrection}\v!on
+ \pack_textrule_correct_depth_yes
+ \pack_textrule_correct_depth_nop
+ \nointerlineskip
+ \noindent\vpack % was \dontleavehmode
+ {\color[\directtextrulesparameter\c!rulecolor]
+ {\hrule
+ \s!depth \directtextrulesparameter\c!rulethickness
+ \s!height\zeropoint
+ \s!width \availablehsize}}}
+
\def\pack_textrule_correct_depth_yes
{\vskip\dimexpr
\strutdp +.5\exheight
@@ -643,15 +668,9 @@
\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
- \noindent\vbox % was \dontleavehmode
- {\color[\directtextrulesparameter\c!rulecolor]
- {\hrule\s!depth\directtextrulesparameter\c!rulethickness\s!height\zeropoint\s!width\availablehsize}}}
- {\pack_textrule_with_text{#1}}%
+ \pack_textrule_with_text_nop
+ \pack_textrule_with_text_yes
+ {#1}%
\ifvmode
\prevdepth\zeropoint
\fi}
diff --git a/tex/context/base/mkiv/pack-obj.lua b/tex/context/base/mkiv/pack-obj.lua
index 3f2b2edfe..ea36b10de 100644
--- a/tex/context/base/mkiv/pack-obj.lua
+++ b/tex/context/base/mkiv/pack-obj.lua
@@ -13,9 +13,11 @@ reusable components.</p>
local context = context
local codeinjections = backends.codeinjections
-
local ctx_doifelse = commands.doifelse
+local report = logs.reporter("objects")
+local trace = false trackers.register("objects",function(v) trace = v end)
+
local nuts = nodes.nuts
local setlink = nuts.setlink
@@ -26,10 +28,7 @@ local new_latelua = nuts.pool.latelua
local settexdimen = tokens.setters.dimen
-local gettexbox = tokens.getters.box
-local settexbox = tokens.setters.box
-local gettexdimen = tokens.getters.dimen
-local gettexcount = tokens.getters.count
+local getcount = tex.getcount
local implement = interfaces.implement
local setmacro = interfaces.setmacro
@@ -54,8 +53,16 @@ end
job.register('job.objects.collected', tobesaved, initializer, nil)
local function saveobject(tag,number,page)
- local t = { number, page }
- tobesaved[tag], collected[tag] = t, t
+ local data = { number, page }
+ tobesaved[tag] = data
+ collected[tag] = data
+end
+
+local function saveobjectspec(specification)
+ local tag = specification.tag
+ local data = { specification.number, specification.page }
+ tobesaved[tag] = data
+ collected[tag] = data
end
local function setobject(tag,number,page)
@@ -128,8 +135,9 @@ objects = {
local objects = objects
function objects.register(ns,id,b,referenced,offset,mode)
- objects.n = objects.n + 1
- nodes.handlers.finalize(gettexbox(b),"object")
+ local n = objects.n + 1
+ objects.n = n
+ nodes.handlers.finalizebox(b)
if mode == 0 then
-- tex
data[ns][id] = {
@@ -147,6 +155,9 @@ function objects.register(ns,id,b,referenced,offset,mode)
mode,
}
end
+ if trace then
+ report("registering object %a (n=%i)",id,n)
+ end
end
function objects.restore(ns,id) -- why not just pass a box number here too (ok, we also set offset)
@@ -159,9 +170,12 @@ function objects.restore(ns,id) -- why not just pass a box number here too (ok,
local hbox = codeinjections.restoreboxresource(index) -- a nut !
if status then
local list = getlist(hbox)
- local page = new_latelua(function()
- saveobject(ns .. "::" .. id,index,gettexcount("realpageno"))
- end)
+ local page = new_latelua {
+ action = saveobjectspec,
+ tag = ns .. "::" .. id,
+ number = index,
+ page = getcount("realpageno"),
+ }
setlink(list,page)
end
setbox("objectbox",hbox)
@@ -170,6 +184,9 @@ function objects.restore(ns,id) -- why not just pass a box number here too (ok,
setbox("objectbox",nil)
settexdimen("objectoff",0) -- for good old times
end
+ if trace then
+ report("restoring object %a",id)
+ end
end
function objects.dimensions(index)
@@ -191,7 +208,7 @@ function objects.reference(ns,id)
end
function objects.page(ns,id)
- return getobjectpage(ns .."::" .. id,gettexcount("realpageno"))
+ return getobjectpage(ns .."::" .. id,getcount("realpageno"))
end
function objects.found(ns,id)
diff --git a/tex/context/base/mkiv/pack-obj.mkiv b/tex/context/base/mkiv/pack-obj.mkiv
index aeb5cb4f4..d08c66494 100644
--- a/tex/context/base/mkiv/pack-obj.mkiv
+++ b/tex/context/base/mkiv/pack-obj.mkiv
@@ -51,7 +51,8 @@
\newdimen\objectht \def\objectheight{\the\objectht}
\newdimen\objectdp \def\objectdepth {\the\objectdp}
-%D If I have time I will use the unreferenced variant for e.g. mp reuse.
+%D If I have time I will use the unreferenced variant for e.g. mp reuse. This can be
+%D rewritten in \LUA\ anyway.
\unexpanded\def\setreferencedobject #1#2{\begingroup\synctexpause\objectoff\objectoffset\inobjecttrue\dowithnextbox{\pack_objects_set_yes{#1}{#2}}}
\unexpanded\def\settightreferencedobject #1#2{\begingroup\synctexpause\objectoff\zeropoint \inobjecttrue\dowithnextbox{\pack_objects_set_yes{#1}{#2}}}
@@ -65,14 +66,8 @@
\newconstant\c_pack_objects_offset_mode % 0=tex 1=box
-\unexpanded\def\pack_objects_temp_check % this will go away
- {\ifnum\texenginefunctionality<6401\relax
- \c_pack_objects_offset_mode\zerocount
- \fi}
-
\unexpanded\def\pack_objects_set_yes#1#2%
- {\pack_objects_temp_check % this will go away
- \ifcase\c_pack_objects_offset_mode
+ {\ifcase\c_pack_objects_offset_mode
\ifzeropt\objectoff
\pack_objects_package_nop\nextbox
\else
@@ -86,8 +81,7 @@
\endgroup}
\unexpanded\def\pack_objects_set_nop#1#2%
- {\pack_objects_temp_check % this will go away
- \ifcase\c_pack_objects_offset_mode
+ {\ifcase\c_pack_objects_offset_mode
\ifzeropt\objectoff
\pack_objects_package_nop\nextbox
\else
diff --git a/tex/context/base/mkiv/pack-rul.lua b/tex/context/base/mkiv/pack-rul.lua
index c9771546c..455d0bff8 100644
--- a/tex/context/base/mkiv/pack-rul.lua
+++ b/tex/context/base/mkiv/pack-rul.lua
@@ -20,42 +20,50 @@ if not modules then modules = { } end modules ['pack-rul'] = {
local type = type
-local context = context
-
-local hlist_code = nodes.nodecodes.hlist
-local vlist_code = nodes.nodecodes.vlist
-local box_code = nodes.listcodes.box
-local line_code = nodes.listcodes.line
-local equation_code = nodes.listcodes.equation
-
-local texsetdimen = tex.setdimen
-local texsetcount = tex.setcount
-
-local implement = interfaces.implement
-
-local nuts = nodes.nuts
-
-local getnext = nuts.getnext
-local getprev = nuts.getprev
-local getlist = nuts.getlist
-local setlist = nuts.setlist
-local getwhd = nuts.getwhd
-local getid = nuts.getid
-local getsubtype = nuts.getsubtype
-local getbox = nuts.getbox
-local getdir = nuts.getdir
-local setshift = nuts.setshift
-local setwidth = nuts.setwidth
-local getwidth = nuts.getwidth
-local setboxglue = nuts.setboxglue
-local getboxglue = nuts.getboxglue
-
-local hpack = nuts.hpack
-local traverse_id = nuts.traverse_id
-local list_dimensions = nuts.dimensions
-local flush_node = nuts.flush
-
-local checkformath = false
+local context = context
+
+local nodecodes = nodes.nodecodes
+local listcodes = nodes.listcodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+
+local boxlist_code = listcodes.box
+local linelist_code = listcodes.line
+local equationlist_code = listcodes.equation
+
+local texsetdimen = tex.setdimen
+local texsetcount = tex.setcount
+
+local implement = interfaces.implement
+
+local nuts = nodes.nuts
+
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local getwhd = nuts.getwhd
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getbox = nuts.getbox
+local getdirection = nuts.getdirection
+local setshift = nuts.setshift
+local setwidth = nuts.setwidth
+local getwidth = nuts.getwidth
+local setboxglue = nuts.setboxglue
+local getboxglue = nuts.getboxglue
+
+local hpack = nuts.hpack
+local getdimensions = nuts.dimensions
+local flush_node = nuts.flush
+
+local traversers = nuts.traversers
+local nexthlist = traversers.hlist
+local nextvlist = traversers.vlist
+local nextlist = traversers.list
+
+local checkformath = false
directives.register("framed.checkmath",function(v) checkformath = v end) -- experiment
@@ -76,24 +84,25 @@ local function doreshapeframedbox(n)
if boxwidth ~= 0 then -- and h.subtype == vlist_code
local list = getlist(box)
if list then
- local function check(n,repack)
+ local hdone = false
+ for n, id, subtype, list in nextlist, list do -- no dir etc needed
local width, height, depth = getwhd(n)
if not firstheight then
firstheight = height
end
lastdepth = depth
noflines = noflines + 1
- local l = getlist(n)
- if l then
- if repack then
- local subtype = getsubtype(n)
- if subtype == box_code or subtype == line_code then
- lastlinelength = list_dimensions(l,getdir(n))
+ if list then
+ if id == hlist_code then
+ if subtype == boxlist_code or subtype == linelist_code then
+ lastlinelength = getdimensions(list)
else
lastlinelength = width
end
+ hdone = true
else
lastlinelength = width
+ -- vdone = true
end
if lastlinelength > maxwidth then
maxwidth = lastlinelength
@@ -107,31 +116,19 @@ local function doreshapeframedbox(n)
totalwidth = totalwidth + lastlinelength
end
end
- local hdone = false
- for h in traverse_id(hlist_code,list) do -- no dir etc needed
- check(h,true)
- hdone = true
- end
- -- local vdone = false
- for v in traverse_id(vlist_code,list) do -- no dir etc needed
- check(v,false)
- -- vdone = true
- end
if not firstheight then
-- done)
elseif maxwidth ~= 0 then
if hdone then
- for h in traverse_id(hlist_code,list) do
- local l = getlist(h)
- if l then
- local subtype = getsubtype(h)
- if subtype == box_code or subtype == line_code then
- local p = hpack(l,maxwidth,'exactly',getdir(h)) -- multiple return value
+ for h, id, subtype, list in nextlist, list do
+ if list and id == hlist_code then
+ if subtype == boxlist_code or subtype == linelist_code then
+ local p = hpack(list,maxwidth,'exactly',getdirection(h)) -- multiple return value
local set, order, sign = getboxglue(p)
setboxglue(h,set,order,sign)
setlist(p)
flush_node(p)
- elseif checkformath and subtype == equation_code then
+ elseif checkformath and subtype == equationlist_code then
-- display formulas use a shift
if nofnonzero == 1 then
setshift(h,0)
@@ -142,7 +139,7 @@ local function doreshapeframedbox(n)
end
end
-- if vdone then
- -- for v in traverse_id(vlist_code,list) do
+ -- for v in nextvlist, list do
-- local width = getwidth(n)
-- if width > maxwidth then
-- setwidth(v,maxwidth)
@@ -164,7 +161,7 @@ local function doreshapeframedbox(n)
texsetdimen("global","framedaveragewidth",averagewidth)
end
-local function doanalyzeframedbox(n)
+local function doanalyzeframedbox(n) -- traverse_list
local box = getbox(n)
local noflines = 0
local firstheight = nil
@@ -172,7 +169,7 @@ local function doanalyzeframedbox(n)
if getwidth(box) ~= 0 then
local list = getlist(box)
if list then
- local function check(n)
+ for n in nexthlist, list do
local width, height, depth = getwhd(n)
if not firstheight then
firstheight = height
@@ -180,11 +177,13 @@ local function doanalyzeframedbox(n)
lastdepth = depth
noflines = noflines + 1
end
- for h in traverse_id(hlist_code,list) do
- check(h)
- end
- for v in traverse_id(vlist_code,list) do
- check(v)
+ for n in nextvlist, list do
+ local width, height, depth = getwhd(n)
+ if not firstheight then
+ firstheight = height
+ end
+ lastdepth = depth
+ noflines = noflines + 1
end
end
end
@@ -210,16 +209,11 @@ local function maxboxwidth(box)
end
local lastlinelength = 0
local maxwidth = 0
- local function check(n,repack)
+ for n, subtype in nexthlist, list do -- no dir etc needed
local l = getlist(n)
if l then
- if repack then
- local subtype = getsubtype(n)
- if subtype == box_code or subtype == line_code then
- lastlinelength = list_dimensions(l,getdir(n))
- else
- lastlinelength = getwidth(n)
- end
+ if subtype == boxlist_code or subtype == linelist_code then
+ lastlinelength = getdimensions(l)
else
lastlinelength = getwidth(n)
end
@@ -228,11 +222,14 @@ local function maxboxwidth(box)
end
end
end
- for h in traverse_id(hlist_code,list) do -- no dir etc needed
- check(h,true)
- end
- for v in traverse_id(vlist_code,list) do -- no dir etc needed
- check(v,false)
+ for n, subtype in nextvlist, list do -- no dir etc needed
+ local l = getlist(n)
+ if l then
+ lastlinelength = getwidth(n)
+ if lastlinelength > maxwidth then
+ maxwidth = lastlinelength
+ end
+ end
end
return maxwidth
end
diff --git a/tex/context/base/mkiv/pack-rul.mkiv b/tex/context/base/mkiv/pack-rul.mkiv
index c208baaf0..3d03942aa 100644
--- a/tex/context/base/mkiv/pack-rul.mkiv
+++ b/tex/context/base/mkiv/pack-rul.mkiv
@@ -18,7 +18,7 @@
%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}{}
+\registerctxluafile{pack-rul}{optimize}
\unprotect
@@ -141,6 +141,7 @@
\setupframed
[\c!width=\v!fit,
\c!height=\v!broad,
+ %\c!minheight=\zeropoint,
%\c!lines=,
\c!offset=.25\exheight, % \defaultframeoffset
\c!empty=\v!no,
@@ -239,7 +240,6 @@
\let\p_framed_backgroundcolor \empty
\let\p_framed_framecolor \empty
\let\p_framed_component \empty
-\let\p_framed_region \empty
\let\p_framed_background \empty
\let\p_framed_rulethickness \empty
\let\p_framed_foregroundcolor \empty
@@ -443,6 +443,8 @@
\newdimen\d_overlay_offset
\newdimen\d_overlay_linewidth
+\let\m_overlay_region\empty
+
% expandable ... in a future version the space will go (in my one can use Overlay*)
\def\overlaywidth {\the\d_overlay_width \space} % We preset the variables
@@ -450,6 +452,7 @@
\def\overlaydepth {\the\d_overlay_depth \space} % values.
\def\overlayoffset {\the\d_overlay_offset \space} % of the frame can be (are)
\def\overlaylinewidth {\the\d_overlay_linewidth\space} % set somewhere else.
+\def\overlayregion {\m_overlay_region}
% public but kind of protected
@@ -553,40 +556,36 @@
\def\pack_framed_process_background_indeed_internal#1% % : in name
{\bgroup
- \setbox\b_framed_extra\hbox{%\bgroup
- \ifzeropt\framedbackgroundoffset
- %\csname\??overlaybuiltin\m_framed_background\endcsname
- #1
- \else
+ \setbox\b_framed_extra\hpack\bgroup
+ \ifzeropt\framedbackgroundoffset\else
\kern-\framedbackgroundoffset
- %\hbox{\csname\??overlaybuiltin\m_framed_background\endcsname}%
- \hbox{#1}%
\fi
- }%\egroup
+ \hbox\bgroup#1\egroup
+ \egroup
\wd\b_framed_extra\zeropoint
\ht\b_framed_extra\framedbackgroundheight
\dp\b_framed_extra\framedbackgrounddepth
\box\b_framed_extra
\egroup}
-\def\pack_framed_process_background_indeed_external#1%
+% \def\pack_framed_process_background_indeed_external#1%
+% {\pack_framed_overlay_initialize
+% \bgroup
+% \setbox\b_framed_extra\hpack\bgroup
+% \ifzeropt\framedbackgroundoffset\else
+% \kern-\framedbackgroundoffset
+% \fi
+% \hbox\bgroup#1\egroup
+% \egroup
+% \wd\b_framed_extra\zeropoint
+% \ht\b_framed_extra\framedbackgroundheight
+% \dp\b_framed_extra\framedbackgrounddepth
+% \box\b_framed_extra
+% \egroup}
+
+\def\pack_framed_process_background_indeed_external
{\pack_framed_overlay_initialize
- \bgroup
- \setbox\b_framed_extra\hbox{%\bgroup
- \ifzeropt\framedbackgroundoffset
- %\csname\??overlay\m_framed_background\endcsname
- #1%
- \else
- \kern-\framedbackgroundoffset
- %\hbox{\csname\??overlay\m_framed_background\endcsname}%
- \hbox{#1}%
- \fi
- }%\egroup
- \wd\b_framed_extra\zeropoint
- \ht\b_framed_extra\framedbackgroundheight
- \dp\b_framed_extra\framedbackgrounddepth
- \box\b_framed_extra
- \egroup}
+ \pack_framed_process_background_indeed_internal}
\def\pack_framed_process_backgrounds#1,#2% #2 gobbles spaces (we could avoid one catch if we have nextbackground)
{\edef\m_framed_background{#1}%
@@ -606,15 +605,23 @@
\def\pack_framed_background_box_content% fuzzy but needed hack, this \vss, otherwise
{\vpack to \framedbackgroundheight{\vss\box\b_framed_normal\vss}} % vertical shift \backgroundheight
-\def\pack_framed_add_region % experiment
- {\ifx\p_framed_region\v!yes
- \anch_mark_region_box\b_framed_normal
- \else
- \anch_mark_tagged_box\b_framed_normal\p_framed_region
+\def\pack_framed_set_region % experiment
+ {\ifx\m_overlay_region\v!yes
+ \edef\m_overlay_region{\reservedautoregiontag}%
\fi}
+% \def\pack_framed_add_region % experiment
+% {\ifx\m_overlay_region\v!yes
+% \anch_mark_region_box\b_framed_normal
+% \else
+% \anch_mark_tagged_box\b_framed_normal\m_overlay_region
+% \fi}
+
+\def\pack_framed_add_region % experiment
+ {\anch_mark_tagged_box\b_framed_normal\m_overlay_region}
+
\def\pack_framed_add_background
- {\setbox\b_framed_normal\hbox % was vbox % see also *1*
+ {\setbox\b_framed_normal\hpack % was vbox % see also *1*
{%\pack_framed_forgetall % can be relaxed
\boxmaxdepth\maxdimen
\framedbackgroundoffset\d_framed_backgroundoffset
@@ -631,7 +638,7 @@
\setlayoutcomponentattribute{\v!background:\p_framed_component}%
\fi
\let\foregroundbox\pack_framed_background_box_content
- \hbox \layoutcomponentboxattribute to \framedbackgroundwidth\bgroup % width in case 'foreground' is used as overlay
+ \hpack \layoutcomponentboxattribute to \framedbackgroundwidth\bgroup % width in case 'foreground' is used as overlay
\the\everybackgroundbox % moved
\expandafter\pack_framed_process_backgrounds\p_framed_background,\s!unknown,\relax % hm, messy .. look into it
\box\b_framed_normal
@@ -692,10 +699,10 @@
\scratchdimen\zeropoint
\fi
\edef\overlaylinecolor{\framedparameter\c!framecolor}% twice, also in background
- \setbox\b_framed_extra\hbox
+ \setbox\b_framed_extra\hpack
{\kern-\d_framed_frameoffset
\raise\scratchdimen
- \hbox{\ifx\overlaylinecolor\empty\else\dousecolorparameter\overlaylinecolor\fi\pack_framed_stroked_box}}%
+ \hpack{\ifx\overlaylinecolor\empty\else\dousecolorparameter\overlaylinecolor\fi\pack_framed_stroked_box}}%
\wd\b_framed_extra\wd\b_framed_normal
\ht\b_framed_extra\ht\b_framed_normal
\dp\b_framed_extra\dp\b_framed_normal
@@ -724,26 +731,45 @@
% \dp\scratchbox\d_framed_target_dp
% \box\scratchbox}
-\def\pack_framed_stroked_box_normal
+\def\pack_framed_stroked_box_normal_opened
{\setbox\scratchbox\vpack \bgroup
- \csname \??framedtop\p_framed_frame\framedparameter\c!topframe \endcsname
+ \csname\??framedtop\p_framed_frame\framedparameter\c!topframe\endcsname
\nointerlineskip % new (needed for fences)
- \hbox \bgroup
- \csname \??framedleft\p_framed_frame\framedparameter\c!leftframe \endcsname
+ \hpack \bgroup
+ \csname\??framedleft\p_framed_frame\framedparameter\c!leftframe\endcsname
\novrule
\s!width \d_framed_target_wd
\s!height\d_framed_target_ht
\s!depth \d_framed_target_dp
- \csname \??framedright\p_framed_frame\framedparameter\c!rightframe \endcsname
+ \csname\??framedright\p_framed_frame\framedparameter\c!rightframe\endcsname
\egroup
\nointerlineskip % new (needed for fences)
- \csname \??framedbottom\p_framed_frame\framedparameter\c!bottomframe\endcsname
+ \csname\??framedbottom\p_framed_frame\framedparameter\c!bottomframe\endcsname
\egroup
\wd\scratchbox\d_framed_target_wd
\ht\scratchbox\d_framed_target_ht
\dp\scratchbox\d_framed_target_dp
\box\scratchbox}
+\def\pack_framed_stroked_box_normal_closed
+ {\hpack\bgroup
+ \scratchdimen.5\d_framed_linewidth
+ \hskip\scratchdimen
+ \clf_framedoutline
+ \dimexpr\d_framed_target_wd-\d_framed_linewidth\relax
+ \dimexpr\d_framed_target_ht-\scratchdimen\relax
+ \dimexpr\d_framed_target_dp-\scratchdimen\relax
+ \d_framed_linewidth
+ \relax
+ \egroup}
+
+\def\pack_framed_stroked_box_normal
+ {\ifx\p_framed_frame\v!closed
+ \pack_framed_stroked_box_normal_closed
+ \else
+ \pack_framed_stroked_box_normal_opened
+ \fi}
+
\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}
@@ -836,7 +862,7 @@
%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\defaultframeoffset{.25\exheight}
\installcorenamespace{regularframedlevel}
@@ -999,9 +1025,11 @@
\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
- \pack_framed_add_region
+ \iftrialtypesetting \else
+ \edef\m_overlay_region{\framedparameter\c!region}%
+ \ifx\m_overlay_region\empty\else
+ \pack_framed_set_region
+ \fi
\fi
\setupcurrentframed[#3]%
\edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds
@@ -1028,6 +1056,11 @@
\pack_framed_add_background
\fi
\pack_framed_restore_depth
+ \iftrialtypesetting \else
+ \ifx\m_overlay_region\empty\else
+ \pack_framed_add_region
+ \fi
+ \fi
\box\b_framed_normal
\egroup}
@@ -1036,9 +1069,9 @@
\unexpanded\def\pack_framed_process_box_indeed#1#2% component box (assumes parameters set and grouped usage)
{\setbox\b_framed_normal\box#2% could actually be \let\b_framed_normal#2
- \edef\p_framed_region{\framedparameter\c!region}%
- \ifx\p_framed_region\empty\else
- \pack_framed_add_region
+ \edef\m_overlay_region{\framedparameter\c!region}%
+ \ifx\m_overlay_region\empty\else
+ \pack_framed_set_region
\fi
\edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds
\d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds
@@ -1061,6 +1094,9 @@
\edef\p_framed_component{#1}%
\pack_framed_add_background
\fi
+ \ifx\m_overlay_region\empty\else
+ \pack_framed_add_region
+ \fi
\box\b_framed_normal
\egroup}
@@ -1602,6 +1638,13 @@
\fi
\ifconditional\c_framed_has_height
\ht\b_framed_normal\d_framed_height
+ \else
+ \edef\p_framed_minheight{\framedparameter\c!minheight}%
+ \ifx\p_framed_minheight\empty \else
+ \ifdim\ht\b_framed_normal<\p_framed_minheight
+ \ht\b_framed_normal\p_framed_minheight
+ \fi
+ \fi
\fi
\edef\p_framed_empty{\framedparameter\c!empty}%
\ifx\p_framed_empty\v!yes
@@ -1609,9 +1652,9 @@
\fi
\pack_framed_stop_orientation % moved here at 2014-05-25
\iftrialtypesetting \else
- \edef\p_framed_region{\framedparameter\c!region}%
- \ifx\p_framed_region\empty\else
- \pack_framed_add_region
+ \edef\m_overlay_region{\framedparameter\c!region}%
+ \ifx\m_overlay_region\empty\else
+ \pack_framed_set_region
\fi
\fi
\d_framed_applied_offset
@@ -1649,6 +1692,11 @@
\fi
\fi
\pack_framed_locator_after\p_framed_location
+ \iftrialtypesetting \else
+ \ifx\m_overlay_region\empty\else
+ \pack_framed_add_region
+ \fi
+ \fi
\box\b_framed_normal
\global\frameddimensionstate % global so to be used directly afterwards !
\ifconditional\c_framed_has_width
@@ -2203,7 +2251,7 @@
\ignorespaces}
\def\dododoformatonelinerbox
- {\hbox to \hsize % maybe \hpack
+ {\hpack to \hsize % was \hbox
{\ifcase\raggedstatus\or\hss\or\hss \fi
\unhbox\nextbox \removeunwantedspaces
\ifcase\raggedstatus\or \or\hss\or\hss\fi}%
@@ -2324,7 +2372,7 @@
\doformatonelinerbox}
\def\pack_framed_format_format_vsize
- {\vbox to \d_framed_height
+ {\vbox to \d_framed_height % no vpack .. maybe grid
\bgroup
\let\postprocessframebox\relax
% \pack_framed_forgetall
@@ -2551,9 +2599,9 @@
\par
\kern-\d_framed_linewidth
\dontleavehmode
- \hpack to \zeropoint{\normalhss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}%
+ \hpack to \zeropoint{\hss\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth}%
\hfill
- \hpack to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\normalhss}%
+ \hpack to \zeropoint{\vrule\s!height\d_framed_linewidth\s!depth\zeropoint\s!width\scratchwidth\hss}%
\par
\nointerlineskip
\kern\scratchoffset
@@ -2792,7 +2840,7 @@
\csname\??framedtextlocation\framedtextparameter\c!location\endcsname
\resetframedtextparameter\c!location
\pack_framed_text_check
- \setbox\b_framed_normal\vbox
+ \setbox\b_framed_normal\vbox % \vpack
\startboxedcontent
\hsize\localhsize
% \insidefloattrue % ? better
@@ -3069,7 +3117,7 @@
\fi}
\def\pack_framed_start_content_indeed
- {\setbox\b_framed_normal\hbox\bgroup % maybe \hpack
+ {\setbox\b_framed_normal\hpack\bgroup
\setlocalhsize
\hsize\localhsize
\scratchleftoffset \framedcontentparameter\c!leftoffset \relax
@@ -3079,16 +3127,16 @@
\advance\hsize\dimexpr-\scratchleftoffset-\scratchrightoffset \relax
\advance\vsize\dimexpr-\scratchtopoffset -\scratchbottomoffset\relax
\kern\scratchleftoffset
- \vbox\bgroup
+ \vpack\bgroup
\vskip\scratchtopoffset
- \vbox\bgroup
- \forgetall
- \blank[\v!disable]}
+ \vbox\bgroup
+ \forgetall
+ \blank[\v!disable]}
\def\pack_framed_stop_content_indeed
- {\removelastskip
- \egroup
- \vskip\scratchbottomoffset
+ {\removelastskip
+ \egroup
+ \vskip\scratchbottomoffset
\egroup
\kern\scratchrightoffset
\egroup
@@ -3132,4 +3180,16 @@
\let\themaxboxwidth\clf_themaxboxwidth
+%D New: slow but ok for most cases:
+
+\unexpanded\def\doifelseframed#1%
+ {\ifcase\numexpr\zerocount
+ \immediateassignment\edef\tempstring{#1\c!frame }\ifx\tempstring\v!on +\plusone\fi
+ \immediateassignment\edef\tempstring{#1\c!topframe }\ifx\tempstring\v!on +\plusone\fi
+ \immediateassignment\edef\tempstring{#1\c!bottomframe}\ifx\tempstring\v!on +\plusone\fi
+ \immediateassignment\edef\tempstring{#1\c!leftframe }\ifx\tempstring\v!on +\plusone\fi
+ \immediateassignment\edef\tempstring{#1\c!rightframe }\ifx\tempstring\v!on +\plusone\fi
+ \immediateassignment\edef\tempstring{#1\c!background }\ifx\tempstring\empty\else+\plusone\fi
+ \relax\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi}
+
\protect \endinput
diff --git a/tex/context/base/mkiv/page-bck.mkiv b/tex/context/base/mkiv/page-bck.mkiv
index b44910bbe..1ec7cdbb8 100644
--- a/tex/context/base/mkiv/page-bck.mkiv
+++ b/tex/context/base/mkiv/page-bck.mkiv
@@ -52,7 +52,7 @@
\let\currentotrbackground\empty
-%D This is the only spot where we hav ea low level dependency on the way
+%D This is the only spot where we have a low level dependency on the way
%D parent chains are defined but we want the speed.
\unexpanded\def\page_backgrounds_check_background
diff --git a/tex/context/base/mkiv/page-box.mkvi b/tex/context/base/mkiv/page-box.mkvi
index 083a94390..10d591631 100644
--- a/tex/context/base/mkiv/page-box.mkvi
+++ b/tex/context/base/mkiv/page-box.mkvi
@@ -15,7 +15,7 @@
\unprotect
-%D The often two step approach (_indeed) saves skippign tokens
+%D The often two step approach (_indeed) saves skipping tokens
%D which is nicer for tracing.
%D Centering the paper area on the print area is determined
@@ -251,14 +251,25 @@
\def\page_boxes_apply_offsets#1%
{\setbox#1\vpack to \paperheight
{\hsize\paperwidth
- \vskip\topspace
- \doifbothsides
- {\hskip\backspace}
- {\hskip\backspace}
- {\hskip\dimexpr\paperwidth-\backspace-\makeupwidth\relax}%
+ \vkern\topspace
+% \parfillskip\zeropoint
+ \hkern\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}%
\box#1}%
\dp#1\zeropoint}
+% \def\page_boxes_apply_offset#box%
+% {\scratchwidth \wd#box%
+% \scratchheight\ht#box%
+% \scratchdepth \dp#box%
+% \setbox#box\vpack
+% {\offinterlineskip
+% \vkern\topoffset
+% \hkern\doifbothsides\backoffset\backoffset{-\backoffset}%
+% \box#box}%
+% \wd#box\scratchwidth
+% \ht#box\scratchheight
+% \dp#box\scratchdepth}
+
% \let\page_boxes_apply_clip_paper \gobbleoneargument
% \let\page_boxes_apply_clip_print_left \gobbleoneargument
% \let\page_boxes_apply_clip_print_right\gobbleoneargument
diff --git a/tex/context/base/mkiv/page-cst.lua b/tex/context/base/mkiv/page-cst.lua
index 155d6e8b0..1c2f5fc0b 100644
--- a/tex/context/base/mkiv/page-cst.lua
+++ b/tex/context/base/mkiv/page-cst.lua
@@ -19,87 +19,86 @@ local trace_cells = false trackers.register("columnsets.cells", function(v) t
local report = logs.reporter("column sets")
-local setmetatableindex = table.setmetatableindex
-
-local properties = nodes.properties
-
-local nodecodes = nodes.nodecodes
-local rulecodes = nodes.rulecodes
-
-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 rule_code = nodecodes.rule
-
-local nuts = nodes.nuts
-local tonode = nuts.tonode
-local tonut = nuts.tonut
-
-local hpack = nuts.hpack
-local vpack = nuts.vpack
-local flushlist = nuts.flush_list
------ removenode = nuts.remove
-
-local setlink = nuts.setlink
-local setlist = nuts.setlist
-local setnext = nuts.setnext
-local setprev = nuts.setprev
-local setsubtype = nuts.setsubtype
-local setbox = nuts.setbox
-local getwhd = nuts.getwhd
-local setwhd = nuts.setwhd
-local getkern = nuts.getkern
-local getpenalty = nuts.getpenalty
-local getwidth = nuts.getwidth
-local getheight = nuts.getheight
-
-local getnext = nuts.getnext
-local getprev = nuts.getprev
-local getid = nuts.getid
-local getlist = nuts.getlist
-local getsubtype = nuts.getsubtype
-local takebox = nuts.takebox
-local takelist = nuts.takelist
-local splitbox = nuts.splitbox
-local getattribute = nuts.getattribute
-local copylist = nuts.copy_list
-
-local getbox = nuts.getbox
-local getcount = tex.getcount
-local getdimen = tex.getdimen
-
-local texsetbox = tex.setbox
-local texsetcount = tex.setcount
-local texsetdimen = tex.setdimen
-
-local theprop = nuts.theprop
-
-local nodepool = nuts.pool
-
-local new_vlist = nodepool.vlist
-local new_trace_rule = nodepool.rule
-local new_empty_rule = nodepool.emptyrule
-
-local context = context
-local implement = interfaces.implement
-
-local variables = interfaces.variables
-local v_here = variables.here
-local v_fixed = variables.fixed
-local v_top = variables.top
-local v_bottom = variables.bottom
-local v_repeat = variables["repeat"]
-local v_yes = variables.yes
-local v_page = variables.page
-local v_first = variables.first
-local v_last = variables.last
------ v_wide = variables.wide
-
-pagebuilders = pagebuilders or { } -- todo: pages.builders
-pagebuilders.columnsets = pagebuilders.columnsets or { }
-local columnsets = pagebuilders.columnsets
+local setmetatableindex = table.setmetatableindex
+
+local properties = nodes.properties
+
+local nodecodes = nodes.nodecodes
+
+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 rule_code = nodecodes.rule
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local hpack = nuts.hpack
+local vpack = nuts.vpack
+local flushlist = nuts.flush_list
+----- removenode = nuts.remove
+
+local setlink = nuts.setlink
+local setlist = nuts.setlist
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local setsubtype = nuts.setsubtype
+local setbox = nuts.setbox
+local getwhd = nuts.getwhd
+local setwhd = nuts.setwhd
+local getkern = nuts.getkern
+local getpenalty = nuts.getpenalty
+local getwidth = nuts.getwidth
+local getheight = nuts.getheight
+
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getsubtype = nuts.getsubtype
+local takebox = nuts.takebox
+local takelist = nuts.takelist
+local splitbox = nuts.splitbox
+local getattribute = nuts.getattribute
+local copylist = nuts.copy_list
+
+local getbox = nuts.getbox
+local getcount = tex.getcount
+local getdimen = tex.getdimen
+
+local texsetbox = tex.setbox
+local texsetcount = tex.setcount
+local texsetdimen = tex.setdimen
+
+local theprop = nuts.theprop
+
+local nodepool = nuts.pool
+
+local new_vlist = nodepool.vlist
+local new_trace_rule = nodepool.rule
+local new_empty_rule = nodepool.emptyrule
+
+local context = context
+local implement = interfaces.implement
+
+local variables = interfaces.variables
+local v_here = variables.here
+local v_fixed = variables.fixed
+local v_top = variables.top
+local v_bottom = variables.bottom
+local v_repeat = variables["repeat"]
+local v_yes = variables.yes
+local v_page = variables.page
+local v_first = variables.first
+local v_last = variables.last
+----- v_wide = variables.wide
+
+pagebuilders = pagebuilders or { } -- todo: pages.builders
+pagebuilders.columnsets = pagebuilders.columnsets or { }
+local columnsets = pagebuilders.columnsets
local data = { [""] = { } }
diff --git a/tex/context/base/mkiv/page-cst.mkiv b/tex/context/base/mkiv/page-cst.mkiv
index f6eede68a..37df4e8b1 100644
--- a/tex/context/base/mkiv/page-cst.mkiv
+++ b/tex/context/base/mkiv/page-cst.mkiv
@@ -765,7 +765,7 @@
% state start | repeat
-% for now (transition)
+%D The old one:
\let\definecolumnset \definepagegrid
\let\setupcolumnset \setuppagegrid
@@ -782,5 +782,6 @@
\let\setupcolumnsetarea \setuppagegridarea
\let\setupcolumnsetareatext\setuppagegridareatext
-\protect
+%D It ends here.
+\protect \endinput
diff --git a/tex/context/base/mkiv/page-ffl.mkiv b/tex/context/base/mkiv/page-ffl.mkiv
index 5536371a7..414cae4ac 100644
--- a/tex/context/base/mkiv/page-ffl.mkiv
+++ b/tex/context/base/mkiv/page-ffl.mkiv
@@ -84,26 +84,29 @@
\def\strc_floats_facing_flush
{\ifnum\c_strc_floats_flushed<\c_strc_floats_saved
- \global\advance\c_strc_floats_flushed\plusone
- \floatingpenalty\zerocount
- \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
+ \strc_floats_facing_flush_indeed % less tracing
+ \fi}
+
+\def\strc_floats_facing_flush_indeed
+ {\global\advance\c_strc_floats_flushed\plusone
+ \floatingpenalty\zerocount
+ \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
- \directboxfromcache{\currentfacingfloat}{\number\c_strc_floats_flushed}%
- \vskip\s_page_one_between_top_insert
- \egroup
- \ifnum\c_strc_floats_saved=\c_strc_floats_flushed
- \global\c_strc_floats_saved \zerocount
- \global\c_strc_floats_flushed\zerocount
- \resetboxesincache{\currentfacingfloat}%
\fi
+ \directboxfromcache{\currentfacingfloat}{\number\c_strc_floats_flushed}%
+ \vkern\s_page_one_between_top_insert
+ \egroup
+ \ifnum\c_strc_floats_saved=\c_strc_floats_flushed
+ \global\c_strc_floats_saved \zerocount
+ \global\c_strc_floats_flushed\zerocount
+ \resetboxesincache{\currentfacingfloat}%
\fi}
\unexpanded\def\strc_floats_facing_setup
diff --git a/tex/context/base/mkiv/page-flt.mkiv b/tex/context/base/mkiv/page-flt.mkiv
index a06c90ec1..83e2b4954 100644
--- a/tex/context/base/mkiv/page-flt.mkiv
+++ b/tex/context/base/mkiv/page-flt.mkiv
@@ -284,16 +284,16 @@
\doifnotinset\v!low\floatspecification\vfill}%
\page_otr_fill_and_eject_page}
-\let\m_page_otf_checked_page_float\relax
+\let\m_page_otr_checked_page_float\relax
\unexpanded\def\page_floats_flush_page_floats % used in postpone
- {\edef\m_page_otf_checked_page_float{\clf_checkedpagefloat}%
- \ifx\m_page_otf_checked_page_float\empty
+ {\edef\m_page_otr_checked_page_float{\clf_checkedpagefloat}%
+ \ifx\m_page_otr_checked_page_float\empty
% nothing
- \else\ifx\m_page_otf_checked_page_float\v!empty
+ \else\ifx\m_page_otr_checked_page_float\v!empty
\emptyhbox \page_otr_fill_and_eject_page % why not dummy_page
\else
- \page_floats_flush_page_floats_indeed\m_page_otf_checked_page_float
+ \page_floats_flush_page_floats_indeed\m_page_otr_checked_page_float
\fi\fi}
% temp hack, needed to prevent floatbox being forgotten during
diff --git a/tex/context/base/mkiv/page-imp.mkiv b/tex/context/base/mkiv/page-imp.mkiv
index c08f9856f..838ad7421 100644
--- a/tex/context/base/mkiv/page-imp.mkiv
+++ b/tex/context/base/mkiv/page-imp.mkiv
@@ -26,7 +26,7 @@
\newtoks\t_page_text_data
\unexpanded\def\starttextdata#1\stoptextdata
- {\global\let\page_shipouts_flush_text_data\page_shipouts_flush_text_data_indeed
+ {\glet\page_shipouts_flush_text_data\page_shipouts_flush_text_data_indeed
\globaladdtotoks\t_page_text_data{#1}}
\let\stoptextdata\relax
@@ -34,7 +34,7 @@
\def\page_shipouts_flush_text_data_indeed
{\vsmashed{\the\t_page_text_data}%
\global\t_page_text_data\emptytoks
- \global\let\page_shipouts_flush_text_data\relax}
+ \glet\page_shipouts_flush_text_data\relax}
\let\page_shipouts_flush_text_data\relax
@@ -63,9 +63,21 @@
\newbox \shipoutscratchbox
-\setnewconstant\shipoutfinalizemethod\plusone % this will be default (we will have two finalizers)
+\setnewconstant\shipoutfinalizemethod\plusone
-\unexpanded\def\installshipoutmethod#1#2% % a handler takes one argument: something to be boxed
+\unexpanded\def\shipoutrange#1#2%
+ {\begingroup
+ \scratchtoks\emptytoks
+ \dostepwiserecurse{#1}{\numexpr#2-\plusone\relax}\plusone{\etoksapp\scratchtoks{##1,}}%
+ \xdef\pagestoshipout{\the\scratchtoks,\number#2}%
+ \doglobal\appendtoks
+ \ifnum\realpageno>\numexpr#2+\plusone\relax
+ \global\everypar{\normalend}%
+ \fi
+ \to\everyaftershipout
+ \endgroup}
+
+\unexpanded\def\installshipoutmethod#1#2% % a handler takes one argument: something to be boxed
{\setgvalue{\??shipoutmethod#1}##1{#2{##1}}} % and shipped out (don't depend on the exact package)
\let\installpagehandler\installshipoutmethod % will go
@@ -73,13 +85,6 @@
\unexpanded\def\invokepagehandler#1%
{\expandnamespacevalue\??shipoutmethod{#1}\v!normal}
-% \def\page_shipouts_handle
-% {\csname\??shipoutmethod\ifcsname\??shipoutmethod\v_page_target_method\endcsname
-% \v_page_target_method
-% \else
-% \v!none
-% \fi\endcsname}
-
\def\page_shipouts_handle
{\ifcsname\??shipoutmethod\v_page_target_method\endcsname
\expandafter\lastnamedcs
@@ -112,12 +117,14 @@
\page_boxes_flush_before
\fi
\the\everybeforeshipout
- \ifcase\shipoutfinalizemethod
+ \ifcase\shipoutfinalizemethod % not nice ... needs thinking
\page_shipouts_handle{#1}%
\else
- \setbox\shipoutscratchbox\hpack{#1}% just in case there are objects there, hook for testing (will go away)
- \finalizeshipoutbox\shipoutscratchbox
- \page_shipouts_handle{\box\shipoutscratchbox}%
+ \setbox\shipoutscratchbox\hpack
+ {#1}% just in case there are objects there, hook for testing (will go away)
+ \page_shipouts_handle
+ {\finalizeshipoutbox\shipoutscratchbox
+ \box\shipoutscratchbox}%
\fi
\setnextrealpageno % so this comes before \everyaftershipout so in fact:
\the\everyaftershipout % at this point we're already on the next realpage
@@ -127,11 +134,12 @@
\def\page_shipouts_ignore#1%
{\begingroup
- \message
- {[\ifarrangingpages arranged \fi page
+ \writestatus\m!system
+ {\ifarrangingpages arranged \fi page
\ifarrangingpages\the\arrangeno\else\the\realpageno\fi\normalspace
- not flushed]}%
- \setbox\scratchbox\hpack{#1}%
+ not flushed}%
+ % \setbox\scratchbox\hpack
+ % {#1}% no finalize
\deadcycles\zerocount
\endgroup}
@@ -154,7 +162,11 @@
\box\scratchbox
\endgroup}
-\newdimen\d_page_shipouts_offset \d_page_shipouts_offset=-1in
+\ifdefined \page_shipout_box \else
+
+ \def\page_shipout_box#1{\normalshipout\box#1\relax} % takes a number
+
+\fi
\def\page_shipouts_normal#1%
{\global\advance\shippedoutpages\plusone
@@ -173,30 +185,36 @@
\normalexpanded{\doifelseinset{\the\shippedoutpages}{\pagestoshipout}}\donetrue\donefalse
\fi
\ifdone
- \setbox\shipoutscratchbox\hpack{#1}%
+ \setbox\shipoutscratchbox\hpack
+ {#1}% finalizes
\ifcase\shipoutfinalizemethod
\finalizeshipoutbox\shipoutscratchbox
\fi
- \normalshipout\vpack
- {\offinterlineskip
- \vskip\d_page_shipouts_offset
- \hskip\d_page_shipouts_offset
+ \setbox\shipoutscratchbox\vpack
+ {\scratchdimen\clf_shipoutoffset\relax
+ \ifdim\scratchdimen=\zeropoint\else
+ \offinterlineskip
+ \vkern\scratchdimen
+ \hkern\scratchdimen
+ \fi
\hpack
{\page_otr_flush_every_stuff
\page_otr_flush_special_content
\box\shipoutscratchbox}}%
+ \page_shipout_box\shipoutscratchbox % takes a box number!
\else
\page_shipouts_ignore{#1}%
\fi}
\def\page_shipouts_arrange#1%
- {% \global\advance\shippedoutpages\plusone
- \begingroup
- \setbox\scratchbox\hpack
+ {\begingroup
+ \setbox\shipoutscratchbox\hpack
+ {#1}% finalizes
+ \setbox\shipoutscratchbox\hpack
{\page_otr_flush_every_stuff
\page_otr_flush_special_content
\box\shipoutscratchbox}%
- \pusharrangedpage\scratchbox
+ \pusharrangedpage\shipoutscratchbox
\deadcycles\zerocount
\endgroup}
@@ -310,14 +328,14 @@
\let\pusharrangedpage\relax
\def\dosetuparrangement#1#2#3#4#5#6#7#8%
- {\global\arrangedpageX #1%
- \global\arrangedpageY #2%
- \global\arrangedpageT #3%
- \global\c_page_marks_nx #4%
- \global\c_page_marks_ny #5%
- \global\let\pusharrangedpage #6%
- \global\let\poparrangedpages #7%
- \global\let\handlearrangedpage#8}
+ {\global\arrangedpageX #1%
+ \global\arrangedpageY #2%
+ \global\arrangedpageT #3%
+ \global\c_page_marks_nx #4%
+ \global\c_page_marks_ny #5%
+ \glet \pusharrangedpage #6%
+ \glet \poparrangedpages #7%
+ \glet \handlearrangedpage#8}
\installpagearrangement {\v!normal}
{\global\arrangingpagesfalse}
diff --git a/tex/context/base/mkiv/page-inf.mkiv b/tex/context/base/mkiv/page-inf.mkiv
index 2064f9f25..4519083bf 100644
--- a/tex/context/base/mkiv/page-inf.mkiv
+++ b/tex/context/base/mkiv/page-inf.mkiv
@@ -112,14 +112,16 @@
{\vfill
\settexthoffset
\hsize\dimexpr\scratchdimen-2\texthoffset\relax
- \hskip\texthoffset % brrrr
+ \hkern\texthoffset % brrrr
\vbox to \zeropoint{\vss\page_info_place_info}%
- \vskip\bodyfontsize}%
+ \vkern\bodyfontsize}%
\dp\b_page_versions\zeropoint
\wd\b_page_versions\scratchdimen
- \setbox#1\hpack{\box#1\hskip-\scratchdimen\box\b_page_versions}}
+ \setbox#1\hpack{\box#1\hkern-\scratchdimen\box\b_page_versions}}
\setupversion % resets
[\v!final]
+\let\page_info_add_to_box\gobbleoneargument
+
\protect \endinput
diff --git a/tex/context/base/mkiv/page-ini.lua b/tex/context/base/mkiv/page-ini.lua
index 5b73c9729..3d5534128 100644
--- a/tex/context/base/mkiv/page-ini.lua
+++ b/tex/context/base/mkiv/page-ini.lua
@@ -41,23 +41,39 @@ function pages.mark(name,list)
local page = list[i]
local sign = false
if type(page) == "string" then
- local s, p = match(page,"([%+%-])(%d+)")
- if s then
- sign, page = s, p
+ local f, t = match(page,"(%d+)[:%-](%d+)")
+ if f and t then
+ f, t = tonumber(f), tonumber(t)
+ if f and t and f <= t then
+ if trace then
+ report("marking page %i upto %i as %a",f,t,name)
+ end
+ for page=f,t do
+ data[page][name] = true
+ end
+ end
+ page = false
+ else
+ local s, p = match(page,"([%+%-])(%d+)")
+ if s then
+ sign, page = s, p
+ end
end
end
- page = tonumber(page)
if page then
- if sign == "+" then
- page = realpage + page
- end
- if sign == "-" then
- report("negative page numbers are not supported")
- else
- if trace then
- report("marking page %i as %a",page,name)
+ page = tonumber(page)
+ if page then
+ if sign == "+" then
+ page = realpage + page
+ end
+ if sign == "-" then
+ report("negative page numbers are not supported")
+ else
+ if trace then
+ report("marking page %i as %a",page,name)
+ end
+ data[page][name] = true
end
- data[page][name] = true
end
end
end
@@ -75,7 +91,6 @@ local function marked(name)
rawset(data,i,nil)
end
local pagedata = rawget(data,realpage)
- print(pagedata and pagedata[name] and true or false)
return pagedata and pagedata[name] and true or false
end
diff --git a/tex/context/base/mkiv/page-ini.mkiv b/tex/context/base/mkiv/page-ini.mkiv
index dc94edf76..38477dc27 100644
--- a/tex/context/base/mkiv/page-ini.mkiv
+++ b/tex/context/base/mkiv/page-ini.mkiv
@@ -80,7 +80,7 @@
\fi}
\def\page_otr_flush_pending_content
- {\vskip\zeropoint\relax
+ {\vkern\zeropoint\relax
\ifvoid\normalpagebox \else
\unvbox\normalpagebox
\penalty\outputpenalty
@@ -256,7 +256,10 @@
\box\pagebox
\egroup \ifconditional\c_page_boxes_save_page_body \copy\b_page_boxes_saved_page_body \fi}
-\appendtoks \restoreglobalbodyfont \to \everybeforepagebody
+\appendtoks
+ \restoreglobalbodyfont
+ \pickupattributes
+\to \everybeforepagebody
\ifdefined\nestednewbox \else \newbox\nestednextbox \fi % hm, still needed?
diff --git a/tex/context/base/mkiv/page-inj.mkvi b/tex/context/base/mkiv/page-inj.mkvi
index cabd07bac..5f48ffd13 100644
--- a/tex/context/base/mkiv/page-inj.mkvi
+++ b/tex/context/base/mkiv/page-inj.mkvi
@@ -124,7 +124,7 @@
\ifx\currentpageinjectionalternative\v!none \else % increment counter but don’t generate output
\forgetparindent
\dontcomplain
- \setconstant\shipoutfinalizemethod\zerocount
+ \setconstant\shipoutfinalizemethod\zerocount % this is messy
\page_injections_flush_indeed
\fi}
diff --git a/tex/context/base/mkiv/page-lay.mkiv b/tex/context/base/mkiv/page-lay.mkiv
index 7b80dadb9..02cc5aa17 100644
--- a/tex/context/base/mkiv/page-lay.mkiv
+++ b/tex/context/base/mkiv/page-lay.mkiv
@@ -13,19 +13,16 @@
\writestatus{loading}{ConTeXt Page Macros / Layout Specification}
-%D Before you start wondering why some of the page related
-%D modules skip upward or left in order to place elements, you
-%D must realize that the reference point is the top left
-%D corner of the main typesetting area. One reason for this
-%D choice is that it suited some viewers that displayed page
-%D areas. Another reason is that margins, edges and top and
-%D bottom areas are kind of virtual, while the header, text
-%D and footer areas normally determine the text flow.
+%D Before you start wondering why some of the page related modules skip upward or
+%D left in order to place elements, you must realize that the reference point is the
+%D top left corner of the main typesetting area. One reason for this choice is that
+%D it suited some viewers that displayed page areas. Another reason is that margins,
+%D edges and top and bottom areas are kind of virtual, while the header, text and
+%D footer areas normally determine the text flow.
\unprotect
-%D The dimensions related to layout areas are represented by
-%D real dimensions.
+%D The dimensions related to layout areas are represented by real dimensions.
\newdimen\paperheight \paperheight = 297mm
\newdimen\paperwidth \paperwidth = 210mm
@@ -69,17 +66,15 @@
\newdimen\totaltextwidth
-%D The next series of dimensions are complemented by left
-%D and rights ones.
+%D The next series of dimensions are complemented by left and rights ones.
\newdimen\margindistance
\newdimen\edgedistance
\newdimen\marginwidth
\newdimen\edgewidth
-%D Because a distance does not really makes sense when there
-%D is no area, we use a zero distance in case there is no
-%D area.
+%D Because a distance does not really makes sense when there is no area, we use a
+%D zero distance in case there is no area.
%D The horizontal distances are:
@@ -149,12 +144,12 @@
\let\currentlayout\empty
\fi
\letlayoutparameter\c!state\v!normal % global ? still needed ?
- \global\let\currentlayout\currentlayout % global
+ \glet\currentlayout\currentlayout % global
\page_layouts_synchronize
\page_layouts_check_next
\or % \setuplayout (reverts to main layout)
\letlayoutparameter\c!state\v!normal % global ? still needed ?
- \global\let\currentlayout\empty % global
+ \glet\currentlayout\empty % global
\page_layouts_synchronize
\page_layouts_check_next
\fi
@@ -244,16 +239,15 @@
\swapmacros\innersidetotal \outersidetotal
\to \everyswapmargins
-%D The papersize macros have a long history and we don't want
-%D to change the commands so they keep looking a bit complex.
+%D The papersize macros have a long history and we don't want to change the commands
+%D so they keep looking a bit complex.
%D \macros
%D {definepapersize}
%D
-%D Before we start calculating layout dimensions, we will
-%D first take care of paper sizes. The first argument can be
-%D either an assignment (for defaults) or an identifier, in
-%D which case the second argument is an assignment.
+%D Before we start calculating layout dimensions, we will first take care of paper
+%D sizes. The first argument can be either an assignment (for defaults) or an
+%D identifier, in which case the second argument is an assignment.
%D
%D \showsetup{definepapersize}
%D
@@ -281,8 +275,8 @@
%D \macros
%D {setuppaper,setuppapersize}
%D
-%D When setting up the papersize on which to typeset and
-%D print, we can also determine some more characteristics.
+%D When setting up the papersize on which to typeset and print, we can also
+%D determine some more characteristics.
%D
%D \showsetup{setuppapersize}
%D
@@ -335,9 +329,8 @@
\def\v_page_target_xy {\numexpr\v_page_target_nx*\v_page_target_ny\relax}
-% Normally we will not use this command directly but for now it
-% works out okay. In the future we might use more of the related
-% commands.
+%D Normally we will not use this command directly but for now it works out okay. In
+%D the future we might use more of the related commands.
\setuplayouttarget
[% these are rather special
@@ -462,7 +455,7 @@
\appendtoks
\page_paper_reinstate
- \global\let\page_paper_reinstate\relax
+ \glet\page_paper_reinstate\relax
\to \everyaftershipout
\unexpanded\def\page_paper_set_restore#1#2%
@@ -538,7 +531,7 @@
\ifx\currentlayouttarget\empty
\let\currentlayouttarget\currentpage
\fi
- \global\let\papersize\currentlayouttarget
+ \glet\papersize\currentlayouttarget
\page_paper_reset_paper
\processcommacommand[\m_page_asked_paper]\page_paper_handle_page_option
\global\paperwidth \layouttargetparameter\c!width \relax
@@ -561,7 +554,7 @@
% locate paper target
\page_paper_reset_print
\processcommacommand[\m_page_asked_print]\page_paper_identify_target
- \global\let\printpapersize\currentlayouttarget
+ \glet\printpapersize\currentlayouttarget
\page_paper_reset_print
\processcommacommand[\m_page_asked_print]\page_paper_handle_print_option
\global\printpaperwidth \layouttargetparameter\c!width \relax
@@ -814,18 +807,18 @@
{\edef\m_page_check{#1}
\edef\m_page_state{\namedlayoutparameter\m_page_check\c!state}%
\ifx\m_page_state\v!start
- \global\let\v_page_layouts_pre_check\currentlayout
- \global\let\currentlayout\m_page_check
+ \glet\v_page_layouts_pre_check\currentlayout
+ \glet\currentlayout\m_page_check
\page_layouts_synchronize
\else\ifx\m_page_state\v!repeat
- \global\let\v_page_layouts_pre_check\relax
- \global\let\currentlayout\m_page_check
+ \glet\v_page_layouts_pre_check\relax
+ \glet\currentlayout\m_page_check
\page_layouts_synchronize
\fi\fi}
\def\page_layouts_check_revert
- {\global\let\currentlayout\v_page_layouts_pre_check
- \global\let\v_page_layouts_pre_check\relax
+ {\glet\currentlayout\v_page_layouts_pre_check
+ \glet\v_page_layouts_pre_check\relax
\page_layouts_synchronize}
\def\page_layouts_check_default
@@ -996,6 +989,7 @@
\newdimen\d_page_adepts_pushed_text_height
\newdimen\d_page_adepts_pushed_footer_height
\newdimen\d_page_adepts_height
+\newdimen\d_page_adapts_delta
\unexpanded\def\adaptlayout
{\dodoubleempty\page_adapts_layout}
@@ -1040,8 +1034,8 @@
\page_otr_command_set_vsize
%
\page_backgrounds_recalculate
- \global\let\page_adepts_push\relax
- \global\let\page_adepts_pop\page_adepts_pop_indeed}
+ \glet\page_adepts_push\relax
+ \glet\page_adepts_pop\page_adepts_pop_indeed}
% \def\page_adapts_check
% {\csname\??pageadaptations\the\ifcsname\??pageadaptations\the\realpageno\endcsname\realpageno\else\zerocount\fi\endcsname}
@@ -1067,8 +1061,8 @@
{\global\textheight \d_page_adepts_pushed_text_height
\global\footerheight\d_page_adepts_pushed_footer_height
\page_layouts_synchronize
- \global\let\page_adepts_push\page_adepts_push_indeed
- \global\let\page_adepts_pop\relax}
+ \glet\page_adepts_push\page_adepts_push_indeed
+ \glet\page_adepts_pop\relax}
\appendtoks \page_adapts_check \to \everystarttext
\appendtoks \page_adapts_reset \to \everyshipout
@@ -1153,8 +1147,8 @@
\def\compensatedinnermakeupmargin
{\dimexpr\ifconditional\innermakeupcompensation+\innermakeupmargin\else\zeropoint\fi\relax}
-\unexpanded\def\freezetextwidth % name will change % \makeupwidth may be set to \textwidth
- {\textwidth\makeupwidth % which is a tricky but valid value
+\unexpanded\def\freezetextwidth % name will change % \makeupwidth may be set to \textwidth
+ {\textwidth\makeupwidth % which is a tricky but valid value
\edef\m_currentlayout_text_width {\layoutparameter\c!textwidth }%
\edef\m_currentlayout_text_margin{\layoutparameter\c!textmargin}%
\ifx\m_currentlayout_text_width\empty \else
@@ -1174,15 +1168,9 @@
{\freezetextwidth
\page_otr_command_set_hsize}
-% The next few are better off in page-ini.mkiv
-
-%D When we start at an even page, we need to swap the layout
-%D differently. We cannot adapt the real page number, since
-%D it is used in cross referencing. The next switch is set
-%D when we start at an even page.
-
-% We could use nested if here plus some \@EAEAEA's but but the
-% next variant has less expansion which is nicer in tracing.
+%D When we start at an even page, we need to swap the layout differently. We cannot
+%D adapt the real page number, since it is used in cross referencing. The next
+%D switch is set when we start at an even page.
% #single #left #right
@@ -1262,7 +1250,7 @@
% \to \everybeforeshipout
\def\goleftonpage % name will change (we could cache)
- {\hskip-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax}
+ {\hkern-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax}
\def\doifelsemarginswap#1#2%
{\doifbothsides{#1}{#1}{#2}}
@@ -1327,12 +1315,9 @@
%D \macros
%D {startlocallayout}
%D
-%D These macros should be used with care. They permit local
-%D layouts (as used in fitting pages, see \type {page-app.tex}).
-
-%D This is kind of obsolete now that we have \type
-%D {\definelayout}, so this hack will disappear in future
-%D versions.
+%D These macros should be used with care. They permit local layouts (as used in
+%D fitting pages, see \type {page-app.tex}). This is kind of obsolete now that we
+%D have \type {\definelayout}, so this hack will disappear in future versions.
\unexpanded\def\startlocallayout
{\globalpushmacro\page_paper_restore
@@ -1367,19 +1352,16 @@
\glet\page_grids_add_to_one\gobbleoneargument
\glet\page_grids_add_to_mix\gobbleoneargument
-%D The default dimensions are quite old and will not change.
-%D The funny fractions were introduced when we went from fixed
-%D dimensions to relative ones. Since \CONTEXT\ is a dutch
-%D package, the dimensions are based on the metric system. The
-%D asymmetrical layout is kind of handy for short
-%D quick||and||dirty stapled documents.
+%D The default dimensions are quite old and will not change. The funny fractions
+%D were introduced when we went from fixed dimensions to relative ones. Since
+%D \CONTEXT\ is a dutch package, the dimensions are based on the metric system. The
+%D asymmetrical layout is kind of handy for short quick||and||dirty stapled
+%D documents.
%D
-%D Although valid, it is not a real good idea to use
-%D dimensions based on the \type {em} unit. First of all,
-%D since there are no fonts loaded yet, this dimension makes
-%D no sense, and second, you would loose track of values,
-%D since they could change while going to a new page,
-%D depending on the current font setting.
+%D Although valid, it is not a real good idea to use dimensions based on the \type
+%D {em} unit. First of all, since there are no fonts loaded yet, this dimension
+%D makes no sense, and second, you would loose track of values, since they could
+%D change while going to a new page, depending on the current font setting.
\setuplayout
[ \c!topspace=.08417508418\paperheight, % 2.5cm
@@ -1435,8 +1417,8 @@
\c!columns=\plusone,
\c!columndistance=\zeropoint]
-%D First we define a whole range of (DIN) papersizes,
-%D of which the A-series makes most sense. We enable checking.
+%D First we define a whole range of (DIN) papersizes, of which the A-series makes
+%D most sense. We enable checking.
\definepapersize [A0] [\c!width=841mm,\c!height=1189mm]
\definepapersize [A1] [\c!width=594mm,\c!height=841mm]
@@ -1477,18 +1459,17 @@
\definepapersize [C9] [\c!width=40mm,\c!height=57mm]
\definepapersize [C10] [\c!width=28mm,\c!height=40mm]
-%D Per August 2004 the rounding of some (seldom used) sizes
-%D were corrected top the latest DIN specifications. Peter
-%D Rolf came up with these and a few more missing sizes.
-%D Watch out: spaces and slashes!
+%D Per August 2004 the rounding of some (seldom used) sizes were corrected top the
+%D latest DIN specifications. Peter Rolf came up with these and a few more missing
+%D sizes. Watch out: spaces and slashes!
\definepapersize [4 A0] [\c!width=1682mm,\c!height=2378mm]
\definepapersize [2 A0] [\c!width=1189mm,\c!height=1682mm]
\definepapersize [C6/C5] [\c!width=114mm,\c!height=229mm]
-%D Because there are no standardized screen sizes, we define
-%D a bunch of sizes with $4:3$ ratios. The \type {S6} size is
-%D nearly as wide as a sheet of \type {A4} paper.
+%D Because there are no standardized screen sizes, we define a bunch of sizes with
+%D $4:3$ ratios. The \type {S6} size is nearly as wide as a sheet of \type {A4}
+%D paper.
\definepapersize [S3] [\c!width=300pt,\c!height=225pt]
\definepapersize [S4] [\c!width=400pt,\c!height=300pt]
@@ -1509,15 +1490,13 @@
\definepapersize [S55] [\c!width=500pt,\c!height=500pt]
\definepapersize [S66] [\c!width=600pt,\c!height=600pt]
-%D One may wonder if \TEX\ should be used for typesetting
-%D \CDROM\ covers, but it does not hurt to have the paper size
-%D ready.
+%D One may wonder if \TEX\ should be used for typesetting \CDROM\ covers, but it
+%D does not hurt to have the paper size ready.
\definepapersize [CD] [\c!width=120mm,\c!height=120mm]
-%D The next series is for our English speaking friends who
-%D decided to stick to non metric values. Thanks to Nelson
-%D Beebe for completing the inch based list.
+%D The next series is for our English speaking friends who decided to stick to non
+%D metric values. Thanks to Nelson Beebe for completing the inch based list.
\definepapersize [letter] [\c!width=8.5in,\c!height=11in]
\definepapersize [ledger] [\c!width=11in,\c!height=17in]
@@ -1573,9 +1552,9 @@
\definepapersize [business] [\c!width=85mm,\c!height=55mm]
\definepapersize [businessUS] [\c!width=3.5in,\c!height=2in]
-%D We can now default to a reasonable size. We match the print
-%D paper size with the typeset paper size. This setting should
-%D come after the first layout specification (already done).
+%D We can now default to a reasonable size. We match the print paper size with the
+%D typeset paper size. This setting should come after the first layout specification
+%D (already done).
% \definepapersize
% [\v!default]
diff --git a/tex/context/base/mkiv/page-lin.lua b/tex/context/base/mkiv/page-lin.lua
index a6b6a12c4..3689c7f8d 100644
--- a/tex/context/base/mkiv/page-lin.lua
+++ b/tex/context/base/mkiv/page-lin.lua
@@ -43,15 +43,14 @@ local v_no = variables.no
local properties = nodes.properties
local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
-local whatcodes = nodes.whatcodes
local listcodes = nodes.listcodes
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local whatsit_code = nodecodes.whatsit
local glyph_code = nodecodes.glyph
-local line_code = listcodes.line
+
+local linelist_code = listcodes.line
local a_displaymath = attributes.private('displaymath')
local a_linenumber = attributes.private('linenumber')
@@ -71,7 +70,7 @@ local getattr = nuts.getattr
local setattr = nuts.setattr
local getlist = nuts.getlist
local getbox = nuts.getbox
------ getdir = nuts.getdir
+----- getdirection = nuts.getdirection
----- getwidth = nuts.getwidth
local getheight = nuts.getheight
local getdepth = nuts.getdepth
@@ -79,8 +78,9 @@ local getdepth = nuts.getdepth
local setprop = nuts.setprop
local getprop = nuts.getprop
-local traverse_id = nuts.traverse_id
-local traverse = nuts.traverse
+local nexthlist = nuts.traversers.hlist
+local nextvlist = nuts.traversers.vlist
+
local copy_node = nuts.copy
----- hpack_nodes = nuts.hpack
local is_display_math = nuts.is_display_math
@@ -224,7 +224,9 @@ implement {
local function check_number(n,a,skip,sameline)
local d = data[a]
if d then
- local tag, skipflag, s = d.tag or "", 0, d.start or 1
+ local tag = d.tag or ""
+ local skipflag = 0
+ local s = d.start or 1
current_list[#current_list+1] = { n, s }
if sameline then
skipflag = 0
@@ -244,7 +246,7 @@ local function check_number(n,a,skip,sameline)
end
local p = checkline(n)
if p then
- ctx_makelinenumber(tag,skipflag,s,p.hsize,p.reverse and "TRT" or "TLT")
+ ctx_makelinenumber(tag,skipflag,s,p.hsize,p.reverse and 1 or 0)
else
report_lines("needs checking")
end
@@ -283,8 +285,8 @@ end
local function listisnumbered(list)
if list then
- for n in traverse_id(hlist_code,list) do
- if getsubtype(n) == line_code then
+ for n, subtype in nexthlist, list do
+ if subtype == linelist_code then
local a = getattr(n,a_linenumber)
if a then
-- a quick test for lines (only valid when \par before \stoplinenumbering)
@@ -306,7 +308,7 @@ local function findnumberedlist(list)
while n do
local id = getid(n)
if id == hlist_code then
- if getsubtype(n) == line_code then
+ if getsubtype(n) == linelist_code then
local a = getattr(n,a_linenumber)
if a then
return a > 0 and list
@@ -383,9 +385,8 @@ function boxed.stage_one(n,nested)
local skip = false
local function check()
- for n in traverse_id(hlist_code,list) do -- attr test here and quit as soon as zero found
- local subtype = getsubtype(n)
- if subtype ~= line_code then
+ for n, subtype in nexthlist, list do
+ if subtype ~= linelist_code then
-- go on
elseif getheight(n) == 0 and getdepth(n) == 0 then
-- skip funny hlists -- todo: check line subtype
@@ -450,7 +451,7 @@ function boxed.stage_one(n,nested)
if not list then
return
end
- for n in traverse_id(vlist_code,list) do
+ for n in nextvlist, list do
local p = properties[n]
if p and p.columngap then
if trace_numbers then
@@ -472,18 +473,21 @@ end
function boxed.stage_two(n,m)
if #current_list > 0 then
m = m or lines.scratchbox
- local t, tn = { }, 0
- for l in traverse_id(hlist_code,getlist(getbox(m))) do
+ local t = { }
+ local tn = 0
+ for l in nexthlist, getlist(getbox(m)) do
tn = tn + 1
t[tn] = copy_node(l) -- use take_box instead
end
for i=1,#current_list do
local li = current_list[i]
- local n, m, ti = li[1], li[2], t[i]
+ local n = li[1]
+ local m = li[2]
+ local ti = t[i]
if ti then
- -- local d = getdir(n)
+ -- local d = getdirection(n)
-- local l = getlist(n)
- -- if d == "TRT" then
+ -- if d == 1 then
-- local w = getwidth(n)
-- ti = hpack_nodes(linked_nodes(new_kern(-w),ti,new_kern(w)))
-- end
diff --git a/tex/context/base/mkiv/page-lin.mkvi b/tex/context/base/mkiv/page-lin.mkvi
index 4348d6770..a27ba5736 100644
--- a/tex/context/base/mkiv/page-lin.mkvi
+++ b/tex/context/base/mkiv/page-lin.mkvi
@@ -46,6 +46,10 @@
\attribute\linenumberattribute\attributeunsetvalue
\to \everyforgetall
+\appendtoks
+ \attribute\linenumberattribute \attributeunsetvalue
+\to \everyinsidefloat
+
\newcount \linenumber % not used
\newbox \b_page_lines_scratch
\newcount \c_page_lines_reference
@@ -275,8 +279,8 @@
\fi\fi\fi
\fi
\the\beforeeverylinenumbering
- \globallet\page_postprocessors_page \page_postprocessors_linenumbers_page
- \globallet\page_postprocessors_column\page_postprocessors_linenumbers_column
+ \glet\page_postprocessors_page \page_postprocessors_linenumbers_page
+ \glet\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
@@ -349,7 +353,7 @@
\d_page_lines_distance\linenumberingparameter\c!distance\relax
\edef\p_align{\linenumberingparameter\c!align}%
\edef\p_location{\linenumberingparameter\c!location}%
- \ifcase\istltdir#dir\relax
+ \ifcase#dir\relax
\settrue \c_page_lines_dir_left_to_right
\else
\setfalse\c_page_lines_dir_left_to_right
diff --git a/tex/context/base/mkiv/page-mix.lua b/tex/context/base/mkiv/page-mix.lua
index 107ac1410..192b8a30a 100644
--- a/tex/context/base/mkiv/page-mix.lua
+++ b/tex/context/base/mkiv/page-mix.lua
@@ -69,8 +69,6 @@ local getpenalty = nuts.getpenalty
local getwidth = nuts.getwidth
local getheight = nuts.getheight
local getdepth = nuts.getdepth
-local traverse_id = nuts.traverse_id
-local traverse = nuts.traverse
local theprop = nuts.theprop
@@ -829,23 +827,6 @@ local function report_deltas(result,str)
report_state("%s, cycles %s, deltas % | t",str,result.cycle or 1,t)
end
--- local function xxcollectinserts(h)
--- local skips, total, order = 0, 0, 0
--- print(h)
--- if h then
--- h = getlist(h)
--- for n in traverse(h) do
--- print(tonode(n))
--- end
--- for n in traverse_id(insert_code,h) do
--- order = order + 1
--- total = total + getheight(n)
--- skips = skips + structures.notes.check_spacing(getsubtype(n),order)
--- end
--- end
--- return skips, total
--- end
-
local function setsplit(specification)
splitruns = splitruns + 1
if trace_state then
diff --git a/tex/context/base/mkiv/page-mix.mkiv b/tex/context/base/mkiv/page-mix.mkiv
index 684ebc585..436c4a1dc 100644
--- a/tex/context/base/mkiv/page-mix.mkiv
+++ b/tex/context/base/mkiv/page-mix.mkiv
@@ -371,6 +371,9 @@
\let\currentmixedcolumnsmethod\empty
+\installmacrostack\currentmixedcolumns
+\installmacrostack\currentmixedcolumnsmethod
+
\unexpanded\def\startmixedcolumns
{\dodoubleempty\page_mix_start_columns}
@@ -385,8 +388,8 @@
\fi\fi}
\unexpanded\def\page_mix_start_columns
- {\pushmacro\currentmixedcolumns
- \pushmacro\currentmixedcolumnsmethod
+ {\push_macro_currentmixedcolumns
+ \push_macro_currentmixedcolumnsmethod
\ifsecondargument
\singleexpandafter\page_mix_start_columns_a
\else\iffirstargument
@@ -462,8 +465,8 @@
\let\stopmixedcolumns\page_mix_columns_stop_nop}
\unexpanded\def\page_mix_fast_columns_start#1%
- {\pushmacro\currentmixedcolumns
- \pushmacro\currentmixedcolumnsmethod
+ {\push_macro_currentmixedcolumns
+ \push_macro_currentmixedcolumnsmethod
\edef\currentmixedcolumns{#1}%
\edef\currentmixedcolumnsmethod{\mixedcolumnsparameter\c!method}%
\mixedcolumnsparameter\c!before\relax % so, it doesn't listen to local settings !
@@ -492,15 +495,15 @@
\endgroup
\begincsname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax
\mixedcolumnsparameter\c!after\relax
- \popmacro\currentmixedcolumnsmethod
- \popmacro\currentmixedcolumns
+ \pop_macro_currentmixedcolumnsmethod
+ \pop_macro_currentmixedcolumns
\the\t_page_mix_at_the_end\global\t_page_mix_at_the_end\emptytoks}
\unexpanded\def\page_mix_columns_stop_nop
{\page_mix_finalize_columns
\endgroup
- \popmacro\currentmixedcolumnsmethod
- \popmacro\currentmixedcolumns
+ \pop_macro_currentmixedcolumnsmethod
+ \pop_macro_currentmixedcolumns
\the\t_page_mix_at_the_end\global\t_page_mix_at_the_end\emptytoks}
% \unexpanded\def\page_mix_columns_stop_yes
@@ -509,12 +512,12 @@
% \begincsname\??mixedcolumnsafter\currentmixedcolumnsmethod\endcsname\relax
% \mixedcolumnsparameter\c!after\relax
% \ifx\currentmixedcolumnsmethod\s!otr
-% \popmacro\currentmixedcolumnsmethod
-% \popmacro\currentmixedcolumns
+% \pop_macro_currentmixedcolumnsmethod
+% \pop_macro_currentmixedcolumns
% \synchronizeoutput % brrr, otherwise sometimes issues in itemize
% \else
-% \popmacro\currentmixedcolumnsmethod
-% \popmacro\currentmixedcolumns
+% \pop_macro_currentmixedcolumnsmethod
+% \pop_macro_currentmixedcolumns
% \fi
% }
diff --git a/tex/context/base/mkiv/page-mul.mkiv b/tex/context/base/mkiv/page-mul.mkiv
index 51af24b6a..957981703 100644
--- a/tex/context/base/mkiv/page-mul.mkiv
+++ b/tex/context/base/mkiv/page-mul.mkiv
@@ -471,7 +471,7 @@
\page_mul_postprocess_lines
\page_mul_postprocess_columns
\dohandleallcolumns
- {\global\setbox\currentcolumnbox\hbox to \d_page_mul_used_width
+ {\global\setbox\currentcolumnbox\hpack to \d_page_mul_used_width
{\box\currentcolumnbox}%
\wd\currentcolumnbox\d_page_mul_used_width
\ifheightencolumns
@@ -479,12 +479,12 @@
\fi}%
\page_mul_calculate_column_result_dimensions
\overlaycolumnfootnotes
- \setbox\columnpagebox\vbox
- {\hbox \ifconditional\c_page_mul_reverse dir TRT \fi to \makeupwidth
+ \setbox\columnpagebox\vpack % \vbox
+ {\ifconditional\c_page_mul_reverse\reversehpack\else\naturalhpack\fi to \makeupwidth
{\hskip\ifconditional\c_page_mul_reverse\d_page_mul_rightskip\else\d_page_mul_leftskip\fi\relax
\dohandleallcolumns
{\finishcolumnbox
- {\setbox\scratchbox\hbox
+ {\setbox\scratchbox\hpack
{\ifx\finishcolumnbox\relax\else\strut\fi
\box\currentcolumnbox}% hm, why strut
\anch_mark_column_box\scratchbox
@@ -499,13 +499,13 @@
\fi
\global\setbox\currenttopcolumnbox\emptybox}%
\advance\scratchdimen \ht\columnpagebox
- \setbox\scratchbox\hbox to \makeupwidth
+ \setbox\scratchbox\hbox to \makeupwidth % between can be something so no \hpack
{\vrule
\s!width \zeropoint
\s!height\scratchdimen
\s!depth \dp\columnpagebox
\dostepwiserecurse\plustwo\nofcolumns\plusone{\hfil\page_mul_between_columns}\hfil}%
- \setbox\columnpagebox\hbox
+ \setbox\columnpagebox\hpack
{\box\columnpagebox
\hskip-\makeupwidth
\box\scratchbox}%
@@ -761,7 +761,7 @@
\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}%
+ \setbox\b_page_mul_notes\hpack{\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
@@ -784,7 +784,7 @@
\getnoflines\scratchdimen
\advance\noflines \minustwo
\scratchdimen\dimexpr\noflines\lineheight+\topskip\relax
- \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}%
+ \setbox\b_page_mul_notes\hpack{\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
@@ -890,6 +890,7 @@
\def\page_mul_routine_balance
{\bgroup
+ % why no \forgetall here
\page_mul_initialize_variables
\widowpenalty\zerocount
\setbox\b_page_mul_balance_content\vbox{\unvbox\normalpagebox}%
@@ -1135,7 +1136,7 @@
% \global\savednoffloats\zerocount
% \global\setfalse\c_page_floats_some_waiting
% \else
-% \global\let\page_floats_column_pop_saved\relax
+% \glet\page_floats_column_pop_saved\relax
% \fi}
%
% \let\page_floats_column_pop_saved\relax
@@ -1249,7 +1250,7 @@
\xdef\insertionheight{\the\dimen0}%
\egroup
\else
- \global\let\insertionheight\zeropoint
+ \glet\insertionheight\zeropoint
\fi}
\def\docolumnroomfloat
@@ -1364,7 +1365,7 @@
\global\setbox\currenttopcolumnbox\vbox
{\snaptogrid\vbox
{\copy\currenttopcolumnbox
- \hbox{\vphantom{\vskip\floatheight}}}% known from previous
+ \hpack{\vphantom{\vskip\floatheight}}}% known from previous
\whitespace % nodig ?
\blank[\rootfloatparameter\c!spaceafter]}%
\else
@@ -1848,4 +1849,17 @@
\s!page_otr_command_test_column =\page_mul_command_test_column
]
+\installfloatmethod \s!multicolumn \v!here \page_mul_place_float_here
+\installfloatmethod \s!multicolumn \v!force \page_mul_place_float_force
+\installfloatmethod \s!multicolumn \v!top \page_mul_place_float_top
+\installfloatmethod \s!multicolumn \v!bottom \page_mul_place_float_bottom
+
+\appendtoks
+ \flushingcolumnfloatsfalse
+\to \everybeforesectionheadhandle
+
+\appendtoks
+ \flushingcolumnfloatstrue
+\to \everyaftersectionheadhandle
+
\protect \endinput
diff --git a/tex/context/base/mkiv/page-one.mkiv b/tex/context/base/mkiv/page-one.mkiv
index 348c301fc..64c4a7134 100644
--- a/tex/context/base/mkiv/page-one.mkiv
+++ b/tex/context/base/mkiv/page-one.mkiv
@@ -73,6 +73,7 @@
\else
\global\vsize\textheight
\fi
+ \global\advance\vsize\d_page_adapts_delta
% 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}
@@ -141,16 +142,17 @@
{\page_otr_command_flush_top_insertions
% this is messy ... we will provide a more tight area (no big deal as we can
% do that at the lua end)
+% \parfillskip\zeropoint
\page_one_registered_text_area_a#1#2% \unvbox <box>
%
\ifgridsnapping
- \vskip\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax
+ \vkern\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax
\prevdepth\openstrutdepth
\page_otr_command_flush_bottom_insertions
\vfil
\else\ifcase\bottomraggednessmode
% ragged (default)
- \vskip\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax
+ \vkern\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax
\prevdepth\openstrutdepth
\page_otr_command_flush_bottom_insertions
\vfil
@@ -159,7 +161,7 @@
\page_otr_command_flush_bottom_insertions
\or
% baseline
- \kern\dimexpr\maxdepth-\d_page_one_natural_depth\relax
+ \vkern\dimexpr\maxdepth-\d_page_one_natural_depth\relax
\page_otr_command_flush_bottom_insertions
\fi\fi
\fakepagenotes}%
@@ -228,6 +230,9 @@
\vskip\s_page_one_between_top_insert
\egroup}
+\let\totaltopinserted\!!zeropoint
+\let\totalbotinserted\!!zeropoint
+
\unexpanded\def\page_one_command_set_top_insertions
{\bgroup
\ifconditional\c_page_floats_some_waiting
@@ -312,38 +317,44 @@
\unexpanded\def\page_one_command_flush_top_insertions
{\ifvoid\namedinsertionnumber\s!topfloat\else
- \ifgridsnapping
- \box\namedinsertionnumber\s!topfloat
- \vskip-\topskip
- \vskip\strutheight % [xx] new: see icare topbleed
- \else
- \ifcase\c_page_floats_insertions_topskip_mode
- % 0: default, do nothing
- \or
- % 1: no topskip (crossed fingers)
- \vskip-\topskip
- \vskip\strutheight
- \fi
- \unvbox\namedinsertionnumber\s!topfloat
- \fi
+ \page_one_command_flush_top_insertions_indeed % less tracing
\fi
\global\d_page_floats_inserted_top\zeropoint}
+\def\page_one_command_flush_top_insertions_indeed
+ {\ifgridsnapping
+ \box\namedinsertionnumber\s!topfloat
+ \vkern-\topskip
+ \vkern\strutheight % [xx] new: see icare topbleed
+ \else
+ \ifcase\c_page_floats_insertions_topskip_mode
+ % 0: default, do nothing
+ \or
+ % 1: no topskip (crossed fingers)
+ \vskip-\topskip % skip !
+ \vkern\strutheight
+ \fi
+ \unvbox\namedinsertionnumber\s!topfloat
+ \fi}
+
\unexpanded\def\page_one_command_flush_bottom_insertions
{\ifvoid\namedinsertionnumber\s!bottomfloat\else
- \ifgridsnapping
- % \floatparameter\c!bottombefore
- \snaptogrid\hbox{\box\namedinsertionnumber\s!bottomfloat}%
- % \floatparameter\c!bottomafter
- \else
- \floatparameter\c!bottombefore
- \unvbox\namedinsertionnumber\s!bottomfloat
- \floatparameter\c!bottomafter
- \fi
+ \page_one_command_flush_bottom_insertions_indeed
\fi
\global\d_page_floats_inserted_bottom\zeropoint
\global\setfalse\c_page_floats_not_permitted}
+\def\page_one_command_flush_bottom_insertions_indeed
+ {\ifgridsnapping
+ % \floatparameter\c!bottombefore
+ \snaptogrid\hbox{\box\namedinsertionnumber\s!bottomfloat}%
+ % \floatparameter\c!bottomafter
+ \else
+ \floatparameter\c!bottombefore
+ \unvbox\namedinsertionnumber\s!bottomfloat
+ \floatparameter\c!bottomafter
+ \fi}
+
\unexpanded\def\page_one_command_flush_floats
{\global\settrue\c_page_floats_flushing
\ifconditional\c_page_floats_some_waiting
diff --git a/tex/context/base/mkiv/page-otr.mkvi b/tex/context/base/mkiv/page-otr.mkvi
index ebaf17ebc..909f5cd4d 100644
--- a/tex/context/base/mkiv/page-otr.mkvi
+++ b/tex/context/base/mkiv/page-otr.mkvi
@@ -97,7 +97,7 @@
\newconstant\c_page_otr_eject_penalty \c_page_otr_eject_penalty -\plustenthousand
\newconstant\c_page_otr_super_penalty \c_page_otr_super_penalty -\plustwentythousand
-\newcount \c_page_otf_trigger_penalty \c_page_otf_trigger_penalty -100010
+\newcount \c_page_otr_trigger_penalty \c_page_otr_trigger_penalty -100010
\newif \ifinotr % we keep this (name) for old times sake
@@ -127,9 +127,9 @@
\endgroup}
\unexpanded\def\installoutputroutine#invoke#action% \invoke \action
- {\global\advance\c_page_otf_trigger_penalty\minusone
- \edef#invoke{\page_otr_trigger{\number\c_page_otf_trigger_penalty}}%
- \setvalue{\??otrtriggers\number\c_page_otf_trigger_penalty}{#action}}
+ {\global\advance\c_page_otr_trigger_penalty\minusone
+ \edef#invoke{\page_otr_trigger{\number\c_page_otr_trigger_penalty}}%
+ \setvalue{\??otrtriggers\number\c_page_otr_trigger_penalty}{#action}}
\unexpanded\def\page_otr_triggered_output_routine_traced
{\ifcsname\??otrtriggers\the\outputpenalty\endcsname
@@ -160,7 +160,7 @@
\ifdefined\everybeforeoutput \else \newtoks\everybeforeoutput \fi
\ifdefined\everyafteroutput \else \newtoks\everyafteroutput \fi
-\def\page_otf_set_engine_output_routine#content%
+\def\page_otr_set_engine_output_routine#content%
{\global\output
{\inotrtrue
\the\everybeforeoutput
@@ -172,7 +172,7 @@
% \ifdefined\everybeforeoutputgroup \else \newtoks\everybeforeoutputgroup \fi
% \ifdefined\everyafteroutputgroup \else \newtoks\everyafteroutputgroup \fi
%
-% \def\page_otf_set_engine_output_routine#content%
+% \def\page_otr_set_engine_output_routine#content%
% {\the\everybeforeoutputgroup
% \global\output
% {\inotrtrue
@@ -187,7 +187,7 @@
% \fi
% \to \everyafteroutputgroup
-\page_otf_set_engine_output_routine\page_otr_triggered_output_routine
+\page_otr_set_engine_output_routine\page_otr_triggered_output_routine
\installoutputroutine\synchronizeoutput % use \triggerpagebuilder instead
{\ifvoid\normalpagebox\else
diff --git a/tex/context/base/mkiv/page-pcl.mkiv b/tex/context/base/mkiv/page-pcl.mkiv
index 53d9f781d..140444fc2 100644
--- a/tex/context/base/mkiv/page-pcl.mkiv
+++ b/tex/context/base/mkiv/page-pcl.mkiv
@@ -30,19 +30,18 @@
\definemeasure[threecolumns][\dimexpr\plusthree\columnwidth+\plustwo \columndistance\relax]
\definemeasure[fourcolumns] [\dimexpr\plusfour \columnwidth+\plusthree\columndistance\relax]
-\newcount\c_page_col_n_of_columns \c_page_col_n_of_columns\plusone
-\newcount\c_page_col_current \c_page_col_current \plusone
-\newdimen\d_page_col_distance
-\newdimen\d_page_col_max_height
-\newdimen\d_page_col_max_width
-%newdimen\d_page_col_balance_step
-\newdimen\d_page_col_column_width
-
-\newdimen\d_page_col_top_height
-\newdimen\d_page_col_top_width
-
-\newdimen\d_page_col_available
-\newdimen\d_page_col_sofar
+\newcount \c_page_col_n_of_columns \c_page_col_n_of_columns\plusone
+\newcount \c_page_col_current \c_page_col_current \plusone
+\newdimen \d_page_col_distance
+\newdimen \d_page_col_max_height
+\newdimen \d_page_col_max_width
+%newdimen \d_page_col_balance_step
+\newdimen \d_page_col_column_width
+\newdimen \d_page_col_top_height
+\newdimen \d_page_col_top_width
+\newdimen \d_page_col_available
+\newdimen \d_page_col_sofar
+\newconditional\c_page_col_page
%D We need to step over empty columns.
@@ -700,6 +699,7 @@
\setuppagecolumns
[\c!distance=1.5\bodyfontsize,
\c!n=\plustwo,
+ \c!page=\v!yes,
%\c!align=, % inherit (also replaces tolerance)
%\c!before=,
%\c!after=,
@@ -727,9 +727,39 @@
\ifdefined \columnwidth \else \newdimen\columnwidth \fi
\ifdefined \columndistance \else \newdimen\columndistance \fi
+\def\page_col_pickup_preceding
+ {\begingroup
+ \setupoutputroutine[\s!mixedcolumn]%
+ \c_page_mix_routine\c_page_mix_routine_intercept
+ \page_otr_trigger_output_routine
+ \ifvoid\b_page_mix_preceding \else
+ % moved here, before the packaging
+ \page_postprocessors_linenumbers_deepbox\b_page_mix_preceding
+ % we need to avoid unvboxing with successive balanced on one page
+ \global\setbox\b_page_mix_preceding\vbox\bgroup
+ % yes or no: \forcestrutdepth
+ \unvbox\b_page_mix_preceding
+ \forcestrutdepth
+ \egroup
+ \wd\b_page_mix_preceding\makeupwidth
+ \global\d_page_mix_preceding_height\ht\b_page_mix_preceding
+ \fi
+ \endgroup}
+
+\def\page_col_flush_preceding
+ {\ifvoid\b_page_mix_preceding \else
+ % this is just one method but ok for now
+ \begingroup
+ % we might need more but for now this is ok
+ \setupfloat[\c!spacebefore=,\c!spaceafter=]%
+ \startplacefigure[\c!location={\v!top,\v!none}]%
+ \box\b_page_mix_preceding
+ \stopplacefigure
+ \endgroup
+ \fi}
+
\unexpanded\def\startpagecolumns
- {\page
- \begingroup
+ {\begingroup
\begingroup
\dosingleempty\page_col_start}
@@ -738,6 +768,15 @@
{\let\currentpagecolumns\empty
\setuppagecolumns[#1]}%
{\edef\currentpagecolumns{#1}}%
+ \edef\p_page{\pagecolumnsparameter\c!page}%
+ \ifx\p_page\empty
+ \setfalse\c_page_col_page
+ \else\ifx\p_page\v!no
+ \setfalse\c_page_col_page
+ \else
+ \settrue\c_page_col_page
+ \page[\p_page]%
+ \fi\fi
\c_page_col_n_of_columns\pagecolumnsparameter\c!n\relax
\ifnum\c_page_col_n_of_columns>\plusone
\expandafter\page_col_start_yes
@@ -769,13 +808,21 @@
\useblankparameter \pagecolumnsparameter
% \useprofileparameter\pagecolumnsparameter
%
- \usemixedcolumnscolorparameter\c!color
+ \usepagecolumnscolorparameter\c!color
%
\setupnotes[\c!width=\textwidth]%
%
\usesetupsparameter\pagecolumnsparameter
%
+ % This will become a method but for now it's good enough
+ %
+ \ifconditional\c_page_col_page\else
+ \page_col_pickup_preceding
+ \fi
\setupoutputroutine[\s!pagecolumn]%
+ \ifconditional\c_page_col_page\else
+ \page_col_flush_preceding
+ \fi
%
\setupfloats[\c!ntop=\plusthousand]%
% \setupfloats[\c!nbottom=\plusthousand]%
diff --git a/tex/context/base/mkiv/page-run.mkiv b/tex/context/base/mkiv/page-run.mkiv
index 19adfaa9c..85da8d9e5 100644
--- a/tex/context/base/mkiv/page-run.mkiv
+++ b/tex/context/base/mkiv/page-run.mkiv
@@ -153,6 +153,7 @@
\v!right=>\c_page_grids_lineno_mode \plusone,
\v!left=>\c_page_grids_lineno_mode \plustwo,
\v!outer=>\c_page_grids_lineno_mode \plusthree,
+ \v!inner=>\c_page_grids_lineno_mode \plusfour,
\v!columns=>\c_page_grids_columns_mode\plusone]% new option
\ifcase\c_page_grids_location
\let\page_grids_add_to_box\gobbleoneargument
@@ -179,13 +180,13 @@
\gridboxlinemode \c_page_grids_line_mode
\gridboxlinenomode\c_page_grids_lineno_mode
\setgridbox\scratchbox\makeupwidth\textheight % todo: check color
- \global\setbox#1\hbox % global ?
+ \global\setbox#1\hpack % global ?
{\ifcase\c_page_grids_location\or\or\box#1\hskip-\makeupwidth\fi
\begingroup % color
\ifcase\layoutcolumns\else
\gray
\setlayoutcomponentattribute{\v!grid:\v!columns}%
- \hbox \layoutcomponentboxattribute to \makeupwidth
+ \hpack \layoutcomponentboxattribute to \makeupwidth
{\dorecurse\layoutcolumns
{\hskip\layoutcolumnwidth
\ifnum\recurselevel<\layoutcolumns
@@ -197,7 +198,7 @@
\hskip-\makeupwidth
\fi
\setlayoutcomponentattribute{\v!grid:\v!lines}%
- \hbox \layoutcomponentboxattribute{\box\scratchbox}%
+ \hpack \layoutcomponentboxattribute{\box\scratchbox}%
\endgroup
\ifcase\c_page_grids_location\or\hskip-\makeupwidth\box#1\fi}%
\stopcolor}
diff --git a/tex/context/base/mkiv/page-sel.mkvi b/tex/context/base/mkiv/page-sel.mkvi
index 335d01187..e11a50f5b 100644
--- a/tex/context/base/mkiv/page-sel.mkvi
+++ b/tex/context/base/mkiv/page-sel.mkvi
@@ -342,7 +342,7 @@
\def\page_selectors_slice_indeed[#filename][#oddsettings][#evensettings]%
{\bgroup
\dontcomplain
- \global\let\slicedpagenumber\!!zerocount
+ \glet\slicedpagenumber\!!zerocount
\getfiguredimensions[#filename]%
\setupcurrentwithpages
[\c!offset=\zeropoint,%
@@ -366,7 +366,7 @@
\c!header=\zeropoint,\c!footer=\zeropoint]%
\fi
\dorecurse\noffigurepages
- {\global\let\slicedpagenumber\recurselevel
+ {\glet\slicedpagenumber\recurselevel
\ifnum\c_page_selectors_n>\plusone
\dorecurse\c_page_selectors_n
{\let\slicedpagestepx\recurselevel
diff --git a/tex/context/base/mkiv/page-set.mkiv b/tex/context/base/mkiv/page-set.mkiv
index 3579e3b48..dd145b322 100644
--- a/tex/context/base/mkiv/page-set.mkiv
+++ b/tex/context/base/mkiv/page-set.mkiv
@@ -248,8 +248,8 @@
\!!counta#1\relax
\fi
\fi
- \relax % needed ! ! ! ! else lookahead over \fi and \@EA
- \@EA\egroup\@EA\scratchcounter\the\!!counta\relax}
+ \relax % needed ! ! ! ! else lookahead over \fi and \expandafter
+ \expandafter\egroup\expandafter\scratchcounter\the\!!counta\relax}
\def\OTRSETsetcorrectcellht
{\bgroup
@@ -260,8 +260,8 @@
\restoreglobalbodyfont
\fi
\advance\!!dimena\strutht
- \relax % needed ! ! ! ! else lookahead over \fi and \@EA
- \@EA\egroup\@EA\scratchdimen\the\!!dimena\relax}
+ \relax % needed ! ! ! ! else lookahead over \fi and \expandafter
+ \expandafter\egroup\expandafter\scratchdimen\the\!!dimena\relax}
\def\doOTRSETsetgridcells#1#2#3#4#5#6% placeholder col row wid hei {data}
{\!!countd#2\advance\!!countd#4\advance\!!countd\minusone
@@ -487,7 +487,7 @@
\let\OTRSETbalht\zeropoint
\def\OTRSETreducegridbox % for the moment no difference between methods
- {\globallet\OTRSETbalht\zeropoint
+ {\glet\OTRSETbalht\zeropoint
\ifcase\OTRSETbalancemethod
% no balancing
\else
@@ -578,7 +578,7 @@
\else
\page_otr_construct_and_shipout\box\OTRfinalpagebox\zerocount % three arguments
\fi \fi
- \globallet\OTRSETbalht\zeropoint
+ \glet\OTRSETbalht\zeropoint
\egroup
\fi}
@@ -642,7 +642,7 @@
{\page_set_command_set_vsize}
\def\doOTRSETcolumnseparator
- {\hbox to \zeropoint{\hss\red\vl\hss}}
+ {\hpack to \zeropoint{\hss\red\vl\hss}}
\let\OTRSETcolumnseparator\relax
@@ -754,7 +754,7 @@
\fi}%
\ifdim\lastskipinotr>\zeropoint
\scratchskip\ht\scratchbox
- \setbox\scratchbox\hbox
+ \setbox\scratchbox\hpack
{\lower\strutdepth\box\scratchbox}%
\dp\scratchbox\scratchdimen
\ht\scratchbox\scratchskip
@@ -942,7 +942,7 @@
\fi
\ifenoughcolumncells
\OTRSETsetgridcells\mofcolumns\columnfirstcell\columnhcells\columnvcells
- {\hbox{\copy#1}}%
+ {\hpack{\copy#1}}%
\page_set_command_set_vsize
\else
\OTRSETsavebox{#1}%
@@ -1155,7 +1155,7 @@
%OTRSETprepareforcolumnslot3{#1}%
%ruledvskip\columnslotspacing\lineheight
\blank[\number\columnslotspacing*\v!line]%
- \snaptogrid\hbox to \hsize{\hss\box#1\hss}% strange, why the centering
+ \snaptogrid\hpack to \hsize{\hss\box#1\hss}% strange, why the centering
\blank[\number\columnslotspacing*\v!line]%
\else
\OTRSETstoreincolumnslotSOMEWHERE2{#1}%
@@ -1336,7 +1336,7 @@
% a quick hack ... will be redone
%
\ifdim\wd\floatbox<\floatwidth \ifhbox\floatbox
- \global\setbox\floatbox\hbox{\unhbox\floatbox}%
+ \global\setbox\floatbox\hpack{\unhbox\floatbox}%
\fi \fi
%
\dp\floatbox\zeropoint
@@ -1417,7 +1417,7 @@
{\advance\totalcolumnspace \OTRSETlocalwidth\recurselevel
\advance\totalcolumnspace \namedcolumnsetparameter{\currentcolumnset:\recurselevel}\c!distance}%
\ifdim\totalcolumnspace>\wd\scratchbox
- \setbox\scratchbox\hbox to \totalcolumnspace{\hss\box\scratchbox\hss}%
+ \setbox\scratchbox\hpack to \totalcolumnspace{\hss\box\scratchbox\hss}%
\fi
\page_set_cell_set\currenthcell\currentvcell\box\scratchbox
\egroup
@@ -1619,17 +1619,17 @@
\def\dostartcolumnset[#1][#2]%
{\increment\columnsetlevel\relax
- \global\let\localcolumnmaxcells\!!zerocount
+ \glet\localcolumnmaxcells\!!zerocount
\global\setfalse\OTRSETfinish
\ifnum\columnsetlevel=\plusone
\bgroup
\saveinterlinespace
- \globallet\columnsetpage\!!plusone
+ \glet\columnsetpage\!!plusone
\def\currentcolumnset{#2}%
\insidecolumnstrue % will be different flag in addition
\setupoutputroutine[\s!columnset]%
\doifelsenothing{#1}
- {\globallet\OTRSETlist\s!default}
+ {\glet\OTRSETlist\s!default}
{\xdef\OTRSETlist{#1}}%
\OTRSETstartnextpage
\OTRSETassignwidths
@@ -1659,7 +1659,7 @@
\global\setbox\OTRfinalpagebox\OTRSETmakegridbox
\ht\OTRfinalpagebox\textheight % signals output that there is content
\OTRSETdofinaloutput
- \globallet\OTRSETbalht\zeropoint
+ \glet\OTRSETbalht\zeropoint
\egroup}
{}}
@@ -1678,7 +1678,7 @@
\ifvoid\OTRfinalpagebox\else
% probably balanced
\ifdim\ht\OTRfinalpagebox<\textheight
- \snaptogrid[\v!page]\hbox{\box\OTRfinalpagebox}%
+ \snaptogrid[\v!page]\hpack{\box\OTRfinalpagebox}%
\else
\box\OTRfinalpagebox
\fi
@@ -1765,7 +1765,7 @@
\def\OTRSETstartnextpage
{\doifsomething\OTRSETlist
{\getfromcommacommand[\OTRSETlist][1]%
- \global\let\OTRSETidentifier\commalistelement
+ \glet\OTRSETidentifier\commalistelement
\xdef\currentcolumnset{\commalistelement}%
\checkcolumnsetparent
\let\newcommalistelement\empty
@@ -1848,7 +1848,7 @@
{\unvbox\normalpagebox
\global\lastskipinotr\lastskip}%
\ifdim\lastskipinotr>\zeropoint
- \global\setbox\b_page_set_preceding\hbox
+ \global\setbox\b_page_set_preceding\hpack
{\lower\strutdepth\box\b_page_set_preceding}%
\fi
\dp\b_page_set_preceding\strutdepth
@@ -1970,7 +1970,7 @@
\def\columnplaceholder#1#2%
{\hbox
- {\setbox\scratchbox\hbox to \hsize
+ {\setbox\scratchbox\hpack to \hsize
{\iftracecolumnset
\hskip-.5ex%
\startcolor[columnset:#2]\vrule\s!width\exheight\s!height.5\exheight\s!depth.5\exheight\stopcolor
@@ -2032,7 +2032,7 @@
\def\page_set_place_float_slot
{\setbox\floatbox\vbox{\page_otr_command_flush_float_box}%
\dp\floatbox\strutdp
- \@EA\uppercasestring\floatmethod\to\floatmethod
+ \expandafter\uppercasestring\floatmethod\to\floatmethod
\OTRSETstoreincolumnslot\floatmethod\floatbox
\page_floats_report_total}
@@ -2337,11 +2337,11 @@
\advance\!!countb \minusone
% new (*)
\doif{\columntextareaparameter\c!location}\v!depth
- {\setbox\scratchbox\hbox{\lower\strutdepth\box\scratchbox}%
+ {\setbox\scratchbox\hpack{\lower\strutdepth\box\scratchbox}%
\dp\scratchbox\zeropoint
\ht\scratchbox\!!heighta}%
%
- \setbox0\hbox
+ \setbox0\hpack
{\ifcase\!!countc
\copy\scratchbox % \box
\else
@@ -2360,7 +2360,7 @@
\advance\!!counta \columntextareaparameter\c!nx
\advance\!!counta -\!!countc
\advance\!!widtha -\!!widthb
- \setbox0\hbox
+ \setbox0\hpack
% {\hskip-\namedlayoutparameter\v!odd\c!backspace
{\hskip-\layoutparameter\c!backspace
\clip
@@ -2560,7 +2560,7 @@
% todo: nboven/onder
%\OTRSETstoreincolumnslotHERE\scratchbox
\edef\floatmethod{\namedframedtextparameter{\??columnsetspan#1}\c!default}%
- \@EA\uppercasestring\floatmethod\to\floatmethod
+ \expandafter\uppercasestring\floatmethod\to\floatmethod
% todo : \v!here -> here enzovoorts
\OTRSETstoreincolumnslot\floatmethod\scratchbox
\checknextindentation[\namedframedtextparameter{\??columnsetspan#1}\c!indentnext]%
@@ -2626,6 +2626,23 @@
% \s!page_otr_command_flush_margin_blocks =\page_set_command_flush_margin_blocks, % not used
]
+\installfloatmethod \s!columnset \v!here \page_set_place_float_here
+\installfloatmethod \s!columnset \v!force \page_set_place_float_force
+\installfloatmethod \s!columnset \v!top \page_set_place_float_top
+\installfloatmethod \s!columnset \v!bottom \page_set_place_float_bottom
+\installfloatmethod \s!columnset \v!page \page_set_place_float_page
+\installfloatmethod \s!columnset \s!tblr \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!lrtb \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!tbrl \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!rltb \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!fxtb \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!btlr \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!lrbt \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!btrl \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!rlbt \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!fxbt \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!fixd \page_set_place_float_force
+
\protect \endinput
% extreme examples (1)
diff --git a/tex/context/base/mkiv/page-sid.mkiv b/tex/context/base/mkiv/page-sid.mkiv
index 6f5d9f357..803381244 100644
--- a/tex/context/base/mkiv/page-sid.mkiv
+++ b/tex/context/base/mkiv/page-sid.mkiv
@@ -41,6 +41,9 @@
\newdimen \d_page_sides_progress
\newdimen \d_page_sides_page_total
+\newdimen \d_page_sides_leftoffset
+\newdimen \d_page_sides_rightoffset
+
%newbox \b_page_sides_bottom
\newcount \c_page_sides_lines_done
@@ -48,6 +51,7 @@
\newcount \c_page_sides_n_of_lines
\newcount \c_page_sides_n_of_hang
\newconstant \c_page_sides_float_type
+\newcount \c_page_sides_hangafter
\newconditional \c_page_sides_short
\newconditional \c_page_sides_flag
@@ -77,6 +81,9 @@
\newdimen \d_page_sides_progression
+\newcount \c_page_sides_m_of_lines
+\newconditional \c_page_sides_delayed
+
\newif \iftracesidefloats % public (might change)
%D Defaults:
@@ -216,6 +223,8 @@
+\compensatedinnermakeupmargin
\relax
\fi
+ \global\d_page_sides_leftoffset \d_page_sides_rightskip
+ \global\d_page_sides_rightoffset\d_page_sides_leftskip
\ifdim\d_page_sides_rightskip>\zeropoint
\global\advance\d_page_sides_rightskip\rightskip
\fi
@@ -394,7 +403,8 @@
\endgroup
\else
\forcestrutdepth
- \fi}
+ \fi
+ \page_otr_command_set_vsize} % new
\def\page_sides_flush_floats
{\par
@@ -541,30 +551,43 @@
\def\page_sides_inject_dummy_lines
{\par
\nointerlineskip
+ % \ifnum\lastpenalty>\zerocount
+ % \penalty\plustenthousand
+ % \fi
\dontleavehmode
\iftracesidefloats
\page_sides_inject_dummy_line_traced
\else
\page_sides_inject_dummy_line_normal
\fi
- \vskip-\dimexpr\lineheight+\strutdp\relax
+ \par
+ % on an empty page we have topskip, say 12pt
+ \ignoreparskip
+ % this can be 18.5pt
+ \kern-\dimexpr\lineheight+\strutdp\relax
+ % so we can actually have a -2.5pt skip on top
\ignoreparskip
\blank[\v!samepage]
- \blank[\v!disable]}
+ \blank[\v!disable]
+ % now say we are negative now
+ \ifdim\pagetotal<\zeropoint
+ % then we're at the top of the page ... quite messy .. i really need to
+ % make the page builder a bit more flexible .. should we do something now?
+ \fi}
%D Checkers:
\def\page_sides_check_floats_after_par
{\page_sides_check_floats_indeed
\ifdim\d_page_sides_pagetotal=\pagetotal \else
- \global\let\page_sides_check_floats\page_sides_check_floats_indeed
+ \glet\page_sides_check_floats\page_sides_check_floats_indeed
\page_sides_flush_floats
\global\c_page_sides_n_of_lines\zerocount % here !
\fi}
\unexpanded\def\page_sides_flush_floats_after_par
{\global\d_page_sides_pagetotal\pagetotal
- \global\let\page_sides_check_floats\page_sides_check_floats_after_par}
+ \glet\page_sides_check_floats\page_sides_check_floats_after_par}
\unexpanded\def\page_sides_forget_floats
{\global\d_page_sides_vsize\d_page_sides_vsize_reset
@@ -651,18 +674,49 @@
\fi
\endgroup}
+% \def\page_sides_analyse_progress
+% {\d_page_sides_progress\d_page_sides_vsize
+% \ifconditional\c_page_sides_flag
+% \advance\d_page_sides_progress-\d_page_sides_page_total
+% \global\setfalse\c_page_sides_flag
+% \else
+% \advance\d_page_sides_progress-\pagetotal
+% \fi}
+
+% test case
+%
+% \usemodule[art-01]
+% \starttext
+% \dorecurse{40}{\line{#1}}
+% \placefigure[left]{}{}
+% \input ward
+% \startitemize
+% \item word \item word \item word \item word
+% \stopitemize
+% \input ward
+% \page
+% \stoptext
+
\def\page_sides_analyse_progress
- {\d_page_sides_progress\d_page_sides_vsize
+ {%\page_otr_command_set_vsize % this is new, otherwise topfloats are not taken into account
+ \d_page_sides_progress\d_page_sides_vsize
\ifconditional\c_page_sides_flag
\advance\d_page_sides_progress-\d_page_sides_page_total
\global\setfalse\c_page_sides_flag
\else
+ \ifdim\dimexpr\d_page_sides_progress+\d_page_sides_bottomtotal\relax>\pagegoal
+ % we adapt pagegoal because we can already have placed something with
+ % everypar and we hope that it triggers a flush, see test above
+ \pagegoal\dimexpr\pagegoal-\d_page_sides_bottomtotal\relax
+ \fi
\advance\d_page_sides_progress-\pagetotal
\fi}
\def\page_sides_analyse_space
{\global\settrue\c_page_sides_flag
- \page_sides_force_depth
+% \ifdim\pagegoal=\maxdimen
+% \pagegoal\textheight % maybe
+% \fi
\global\d_page_sides_page_total \pagetotal % global
\ifnum\c_page_sides_float_type<\plusfour
\global\d_page_sides_width \zeropoint
@@ -716,8 +770,18 @@
%D As we have no clear end of one or more paragraphs we only have pre float
%D skips.
-\def\page_sides_handle_float#1% grid (4) is rather experimental
- {\page_sides_check_horizontal_skips
+\newconstant\c_page_sides_page_method % will be: \c_page_sides_page_method\plusone
+
+\def\page_otr_force_new_page_one
+ {\vskip\d_page_sides_height
+ \penalty\outputpenalty
+ \vskip-\dimexpr\d_page_sides_height-\strutdp\relax
+ \prevdepth\strutdp}
+ %\ignoreparskip}
+
+\def\page_sides_handle_float#1%
+ {\page_sides_initialize_checker
+ \page_sides_check_horizontal_skips
\page_sides_check_vertical_skips
\page_sides_apply_horizontal_shift
\page_sides_check_previous_float
@@ -726,13 +790,26 @@
\page_sides_relocate_float{#1}%
\page_sides_apply_vertical_shift
\page_sides_analyse_space
- \ifconditional\c_page_floats_room \else
- \page_otr_fill_and_eject_page
+ \ifconditional\c_page_floats_room
+ \global\setfalse\c_page_sides_delayed
+ % we're ok
+ \else
+ \global\settrue\c_page_sides_delayed
+ \global\c_page_sides_m_of_lines\c_page_sides_n_of_lines
+ \ifcase\c_page_sides_page_method
+ \page_otr_fill_and_eject_page
+ \or
+ \page_otr_force_new_page_one
+ \else
+ \page_otr_fill_and_eject_page
+ \fi
+ \global\c_page_sides_n_of_lines\c_page_sides_m_of_lines
\page_sides_analyse_space
%\page_sides_inject_before
\page_sides_inject_dummy_lines
\fi
\page_sides_place_float
+ \global\setfalse\c_page_sides_delayed
\page_sides_check_floats_reset
\page_sides_wrapup}
@@ -740,8 +817,7 @@
{% we need to do this aftergroup
\aftergroup\par
\aftergroup\ignoreparskip
- \aftergroup\ignorespaces
- }
+ \aftergroup\ignorespaces}
\def\page_sides_check_floats_indeed
{\page_sides_analyse_progress
@@ -752,7 +828,16 @@
\fi
\parskip\s_spac_whitespace_parskip} % not needed
-\let\page_sides_check_floats\page_sides_check_floats_indeed
+% \let\page_sides_check_floats\page_sides_check_floats_indeed
+
+\let\page_sides_check_floats\relax
+
+\def\page_sides_initialize_checker
+ {\ifx\page_sides_check_floats\relax
+ \glet\page_sides_check_floats\page_sides_check_floats_indeed
+ \clf_enablesidefloatchecker
+ \glet\page_sides_initialize_checker\relax
+ \fi}
\unexpanded\def\page_sides_check_floats_tracer
{\begingroup
@@ -771,8 +856,30 @@
\fi
\endgroup}
+% tricky test:
+
+% \starttext
+% \dorecurse{33}{\line{#1}}
+% \placefigure[left]{}{}
+% \input ward
+% \startitemize
+% \item word \item word \item word \item word
+% \stopitemize
+% \input ward
+% \page
+% \placefigure[left]{}{}
+% \dontleavehmode \begingroup \input ward \par \endgroup
+% \dontleavehmode \begingroup \input ward \par \endgroup
+% \dontleavehmode \begingroup \input ward \par \endgroup
+% \input ward
+% \stoptext
+
\unexpanded\def\page_sides_check_floats_set
{\edef\p_sidethreshold{\floatparameter\c!sidethreshold}%
+ \ifconditional\c_page_sides_delayed
+ % For Alan's hanging right float that moved to the next page.
+ \d_page_sides_progress\zeropoint
+ \fi
\ifx\p_sidethreshold\v!old
\d_page_sides_progression\dimexpr\d_page_sides_progress+\strutht-\roundingeps\relax
\c_page_sides_n_of_hang\d_page_sides_progression
@@ -785,8 +892,14 @@
\dimexpr\d_page_sides_progress-\p_sidethreshold\relax
\fi
\getnoflines\d_page_sides_progression
+ % this can be an option
+ \ifdim\dimexpr\noflines\lineheight>\dimexpr\pagegoal-\pagetotal\relax
+ \getrawnoflines\d_page_sides_progression
+ \fi
+ %
\c_page_sides_n_of_hang\noflines
\fi
+ \global\c_page_sides_hangafter\zerocount
\ifnum\c_page_sides_n_of_hang>\zerocount
\ifcase\c_page_sides_n_of_lines
\else
@@ -822,6 +935,7 @@
\else
\hangindent \ifnum\c_page_sides_float_type>\plusfour -\fi\d_page_sides_width
\hangafter-\c_page_sides_n_of_hang
+ \global\c_page_sides_hangafter\hangafter
\fi
\fi
\global\advance\c_page_sides_checks_done \plusone
@@ -830,7 +944,16 @@
\fi}
\unexpanded\def\page_sides_check_floats_reset
- {\global\c_page_sides_checks_done\zerocount}
+ {\ifcase\c_page_sides_checks_done\else
+ \ifcase\c_page_sides_hangafter\else
+ % we need to deal with par's ending in a group which would restore
+ % hang parameters
+ \global\c_page_sides_hangafter\zerocount
+ \hangindent\zeropoint
+ \fi
+ % \global % no, otherwise a next hangindent won't work
+ \c_page_sides_checks_done\zerocount
+ \fi}
\unexpanded\def\page_sides_synchronize_floats
{\ifinner \else
diff --git a/tex/context/base/mkiv/page-smp.mkiv b/tex/context/base/mkiv/page-smp.mkiv
new file mode 100644
index 000000000..2711c9944
--- /dev/null
+++ b/tex/context/base/mkiv/page-smp.mkiv
@@ -0,0 +1,59 @@
+%D \module
+%D [ file=page-smp, % was: core-mul, page-mul
+%D version=1998.03.15,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Simple Multi Column Output,
+%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 The old one:
+
+\definemixedcolumns
+ [\v!columns]
+ % compatible with columns default :
+ [\c!balance=\v!yes,
+ \c!blank={\v!line,\v!fixed}]
+
+\unexpanded\def\setupcolumns
+ {\setupmixedcolumns[\v!columns]}
+
+%D This will be replaced by mixed box.
+
+\unexpanded\def\startsimplecolumns
+ {\dosingleempty\page_simple_start}
+
+\def\page_simple_start[#1]%
+ {\bgroup
+ \setsimplecolumnshsize[#1]%
+ \nopenalties
+ \setbox\scratchbox\vbox\bgroup
+ \forgetall} % \blank[\v!disable]
+
+\unexpanded\def\stopsimplecolumns
+ {\removebottomthings
+ \egroup
+ \rigidcolumnbalance\scratchbox
+ \egroup}
+
+\unexpanded\def\setsimplecolumnshsize[#1]%
+ {\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}}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/page-spr.mkiv b/tex/context/base/mkiv/page-spr.mkiv
index dc1e013d5..bb95ee467 100644
--- a/tex/context/base/mkiv/page-spr.mkiv
+++ b/tex/context/base/mkiv/page-spr.mkiv
@@ -23,15 +23,32 @@
% beware, ugly overload, to be redone
+% \def\normalsettextpagecontent#1#2#3% #2 and #3 will disappear
+% {\setbox#1\hbox
+% {\setlayoutcomponentattribute{\v!page:\v!text}%
+% \vbox \layoutcomponentboxattribute to \textheight
+% {\offinterlineskip
+% \freezetextwidth
+% \hsize\textwidth % local variant of \sethsize
+% \boxmaxdepth\maxdepth
+% \noindent % content can be < \hsize
+% \page_otr_command_package_contents#2#3}}%
+% \dp#1\zeropoint
+% \ifconditional\c_page_spread_busy
+% \normalsettextpagecontent_spread{#1}%
+% \else
+% \normalsettextpagecontent_normal{#1}%
+% \fi}
+
\def\normalsettextpagecontent#1#2#3% #2 and #3 will disappear
- {\setbox#1\hbox
+ {\setbox#1\hpack
{\setlayoutcomponentattribute{\v!page:\v!text}%
- \vbox \layoutcomponentboxattribute to \textheight
+ \vpack \layoutcomponentboxattribute to \textheight
{\offinterlineskip
\freezetextwidth
\hsize\textwidth % local variant of \sethsize
\boxmaxdepth\maxdepth
- \noindent % content can be < \hsize
+ \noindent % content can be < \hsize
\page_otr_command_package_contents#2#3}}%
\dp#1\zeropoint
\ifconditional\c_page_spread_busy
@@ -40,12 +57,18 @@
\normalsettextpagecontent_normal{#1}%
\fi}
+% \def\normalsettextpagecontent_normal#1%
+% {\setbox#1\hbox to \makeupwidth
+% {\hss\box#1\hss}} % never change the \hss's
+
\def\normalsettextpagecontent_normal#1%
- {\setbox#1\hbox to \makeupwidth
- {\hss\box#1\hss}} % never change the \hss's
+ {\ifdim\wd#1=\makeupwidth\else
+ \setbox#1\hpack to \makeupwidth
+ {\hss\box#1\hss}% never change the \hss's
+ \fi}
\def\normalsettextpagecontent_spread#1%
- {\setbox#1\hbox to \makeupwidth
+ {\setbox#1\hpack to \makeupwidth
{\ifvoid\b_page_spread_content
\ifconditional\c_page_spread_once
\box#1%
diff --git a/tex/context/base/mkiv/page-str.lua b/tex/context/base/mkiv/page-str.lua
index 4aeffffd8..ebb49a918 100644
--- a/tex/context/base/mkiv/page-str.lua
+++ b/tex/context/base/mkiv/page-str.lua
@@ -20,18 +20,27 @@ local implement = interfaces.implement
local nodecodes = nodes.nodecodes
-local slide_node_list = nodes.slide
-local write_node = nodes.write
-local flush_node = nodes.flush
-local copy_node_list = nodes.copy_list
-local vpack_node_list = nodes.vpack
+local nuts = nodes.nuts
+local tonut = nodes.tonut
+local slide_node_list = nuts.slide
+local write_node = nuts.write
+local flush_node = nuts.flush
+local copy_node_list = nuts.copy_list
+local vpack_node_list = nuts.vpack
+
+local getbox = nuts.getbox
+local setlink = nuts.setlink
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local getwhd = nuts.getwhd
+local setwhd = nuts.setwhd
local settings_to_array = utilities.parsers.settings_to_array
local enableaction = nodes.tasks.enableaction
local texgetdimen = tex.getdimen
-local texgetbox = tex.getbox
+----- texgetbox = tex.getbox
local trace_collecting = false trackers.register("streams.collecting", function(v) trace_collecting = v end)
local trace_flushing = false trackers.register("streams.flushing", function(v) trace_flushing = v end)
@@ -41,7 +50,11 @@ local report_streams = logs.reporter("streams")
streams = streams or { } -- might move to the builders namespace
local streams = streams
-local data, name, stack = { }, nil, { }
+-- maybe store head and tail ... first we need usage
+
+local data = { }
+local name = nil
+local stack = { }
function streams.enable(newname)
if newname == "default" then
@@ -66,7 +79,7 @@ end
function streams.collect(head,where)
if name and head and name ~= "default" then
- local tail = node.slide(head)
+ local head = tonut(head)
local dana = data[name]
if not dana then
dana = { }
@@ -75,7 +88,7 @@ function streams.collect(head,where)
local last = dana[#dana]
if last then
local tail = slide_node_list(last)
- tail.next, head.prev = head, tail
+ setlink(tail,head)
elseif last == false then
dana[#dana] = head
else
@@ -84,9 +97,9 @@ function streams.collect(head,where)
if trace_collecting then
report_streams("appending snippet %a to slot %s",name,#dana)
end
- return nil, true
+ return nil
else
- return head, false
+ return head
end
end
@@ -118,7 +131,7 @@ function streams.flush(name,copy) -- problem: we need to migrate afterwards
for i=1,dn do
local di = dana[i]
if di then
- write_node(copy_node_list(di.list)) -- list, will be option
+ write_node(copy_node_list(getlist(di))) -- list, will be option
end
end
if copy then
@@ -131,8 +144,8 @@ function streams.flush(name,copy) -- problem: we need to migrate afterwards
for i=1,dn do
local di = dana[i]
if di then
- write_node(di.list) -- list, will be option
- di.list = nil
+ write_node(getlist(di)) -- list, will be option
+ setlist(di)
flush_node(di)
end
end
@@ -167,7 +180,7 @@ function streams.synchronize(list) -- this is an experiment !
local slot = dana[m]
if slot then
local vbox = vpack_node_list(slot)
- local ht, dp = vbox.height, vbox.depth
+ local wd, ht, dp = getwhd(vbox)
if ht > height then
height = ht
end
@@ -191,32 +204,36 @@ function streams.synchronize(list) -- this is an experiment !
local dana = data[name]
local vbox = dana[m]
if vbox then
- local delta_height = height - vbox.height
- local delta_depth = depth - vbox.depth
+ local wd, ht, dp = getwhd(vbox)
+ local delta_height = height - ht
+ local delta_depth = depth - dp
if delta_height > 0 or delta_depth > 0 then
if false then
-- actually we need to add glue and repack
- vbox.height, vbox.depth = height, depth
+ setwhd(vbox,false,height,depth)
if trace_flushing then
report_streams("slot %s of %a with delta (%p,%p) is compensated",m,i,delta_height,delta_depth)
end
else
-- this is not yet ok as we also need to keep an eye on vertical spacing
-- so we might need to do some splitting or whatever
- local tail = vbox.list and slide_node_list(vbox.list)
- local n, delta = 0, delta_height -- for tracing
+ local list = getlist(vbox)
+ local tail = list and slide_node_list(list)
+ local n = 0
+ local delta = delta_height -- for tracing
while delta > 0 do
-- we need to add some interline penalties
- local line = copy_node_list(texgetbox("strutbox"))
- line.height, line.depth = strutht, strutdp
+ local line = copy_node_list(getbox("strutbox"))
+ setwhd(line,false,strutht,strutdp)
if tail then
- tail.next, line.prev = line, tail
+ setlink(tail,line)
end
- tail = line
- n, delta = n +1, delta - struthtdp
+ tail = line
+ n = n + 1
+ delta = delta - struthtdp
end
- dana[m] = vpack_node_list(vbox.list)
- vbox.list = nil
+ dana[m] = vpack_node_list(getlist(vbox))
+ setlist(vbox)
flush_node(vbox)
if trace_flushing then
report_streams("slot %s:%s with delta (%p,%p) is compensated by %s lines",m,i,delta_height,delta_depth,n)
@@ -230,6 +247,8 @@ function streams.synchronize(list) -- this is an experiment !
end
end
+-- hm, nut or node
+
tasks.appendaction("mvlbuilders", "normalizers", "streams.collect")
tasks.disableaction("mvlbuilders", "streams.collect")
diff --git a/tex/context/base/mkiv/page-str.mkiv b/tex/context/base/mkiv/page-str.mkiv
index 57a465603..354c1f3c3 100644
--- a/tex/context/base/mkiv/page-str.mkiv
+++ b/tex/context/base/mkiv/page-str.mkiv
@@ -56,7 +56,7 @@
\unexpanded\def\disableoutputstream
{\inoutputstreamfalse
- \global\let\currentoutputstream\s!default
+ \glet\currentoutputstream\s!default
\clf_disablestream}
\unexpanded\def\startoutputstream[#1]%
diff --git a/tex/context/base/mkiv/page-txt.mkvi b/tex/context/base/mkiv/page-txt.mkvi
index b043b60c7..97668c143 100644
--- a/tex/context/base/mkiv/page-txt.mkvi
+++ b/tex/context/base/mkiv/page-txt.mkvi
@@ -98,8 +98,8 @@
{\expandafter\normalgdef\csname\??layouttextsreset#vertical\endcsname{\page_layouts_set_element_status_normal#vertical}}
\def\page_layouts_set_element_status_normal#vertical%
- {\global\expandafter\let\csname\namedlayoutelementhash#vertical\c!state\endcsname\v!normal
- \global\expandafter\let\csname\??layouttextsreset#vertical\endcsname\relax
+ {\expandafter\glet\csname\namedlayoutelementhash#vertical\c!state\endcsname\v!normal
+ \expandafter\glet\csname\??layouttextsreset#vertical\endcsname\relax
\page_layouts_synchronize_element{#vertical}}
\def\page_layouts_synchronize_element#vertical%
@@ -527,10 +527,10 @@
\page_layouts_place_text_line_right
\page_layouts_place_text_line_left
\namedlayoutelementparameter\currentlayouttextline\c!after
- \kern\zeropoint}% keep the \dp, beware of \vtops, never change this!
+ \vkern\zeropoint}% keep the \dp, beware of \vtops, never change this!
\dp\b_page_layouts_element\zeropoint
\box\b_page_layouts_element
- \vskip-#height\relax}
+ \vkern-#height\relax}
\let\page_layouts_extra_at_margin_left \plusone
\let\page_layouts_extra_at_margin_right\plustwo
@@ -831,21 +831,21 @@
\calculatereducedvsizes
\swapmargins
\offinterlineskip
- \vskip\dimexpr-\topheight-\topdistance\relax
+ \vkern\dimexpr-\topheight-\topdistance\relax
\the\toptextcontent
- \vskip\dimexpr\topheight+\topdistance\relax
+ \vkern\dimexpr\topheight+\topdistance\relax
\the\headertextcontent
- \vskip\dimexpr\headerheight+\headerdistance+\textdistance\relax
+ \vkern\dimexpr\headerheight+\headerdistance+\textdistance\relax
\anch_positions_place_anchors
- \vskip\dimexpr-\textdistance-\textheight\relax
+ \vkern\dimexpr-\textdistance-\textheight\relax
\the\texttextcontent
- \vskip\textheight
+ \vkern\textheight
\the\everyendoftextbody
- \vskip\footerdistance
+ \vkern\footerdistance
\the\footertextcontent
- \vskip\dimexpr\footerheight+\bottomdistance\relax
+ \vkern\dimexpr\footerheight+\bottomdistance\relax
\the\bottomtextcontent
- \vskip\bottomheight
+ \vkern\bottomheight
\vfilll}%
\smashbox\b_page_layouts_element
\box\b_page_layouts_element}
@@ -854,16 +854,20 @@
% \let\page_prepare_backgrounds\gobbleoneargument
% \fi
+% only for very special controlled cases or experiments:
+
+\let\page_scale_text_box\gobbleoneargument
+
\def\page_insert_body#1#2%
{\setbox\b_page_layouts_element\vpack
{\offinterlineskip
\calculatereducedvsizes
\calculatehsizes
\swapmargins
- \vskip\dimexpr\headerheight+\headerdistance+\textdistance\relax
+ \vkern\dimexpr\headerheight+\headerdistance+\textdistance\relax
\dontleavehmode
%\page_prepare_backgrounds{#2}%
- \hbox to \makeupwidth
+ \hpack to \makeupwidth
{\begingroup
\swapmargins
\goleftonpage
@@ -880,6 +884,7 @@
\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
+ \page_scale_text_box\b_page_layouts_element
\box\b_page_layouts_element
\begingroup
\ifdim\rightmarginwidth>\zeropoint
diff --git a/tex/context/base/mkiv/publ-aut.lua b/tex/context/base/mkiv/publ-aut.lua
index be0c771a3..e74c7ee18 100644
--- a/tex/context/base/mkiv/publ-aut.lua
+++ b/tex/context/base/mkiv/publ-aut.lua
@@ -16,6 +16,7 @@ local lpeg = lpeg
local type, next, tostring, tonumber = type, next, tostring, tonumber
local concat, sortedhash = table.concat, table.sortedhash
local utfsub = utf.sub
+local find = string.find
local formatters = string.formatters
local P, S, C, V, Cs, Ct, Cg, Cf, Cc = lpeg.P, lpeg.S, lpeg.C, lpeg.V, lpeg.Cs, lpeg.Ct, lpeg.Cg, lpeg.Cf, lpeg.Cc
@@ -38,6 +39,8 @@ local chardata = characters.data
local trace_hashing = false trackers.register("publications.authorhash", function(v) trace_hashing = v end)
+local expand_authors = false directives.register("publications.prerollauthor", function(v) expand_authors = v end)
+
local report = logs.reporter("publications","authors")
local report_cite = logs.reporter("publications","cite")
@@ -61,8 +64,8 @@ local v_last = interfaces.variables.last
local space = lpegpatterns.whitespace
local comma = P(",")
-local period = P(".")
-local dash = P("-")
+local period = P(".") + P("{.}")
+local dash = P("-") + P("{-}")
local firstcharacter = lpegpatterns.utf8byte
local utf8character = lpegpatterns.utf8character
local p_and = space^1 * (P("and") + P("&&") + P("++")) * space^1
@@ -123,6 +126,8 @@ end
local authormap = allocate()
publications.authormap = authormap
+local prerollcmdstring = publications.prerollcmdstring
+
local function splitauthor(author,justsplit)
local detail, remapped
if not justsplit then
@@ -142,6 +147,9 @@ local function splitauthor(author,justsplit)
end
local author = remapped or author
local firstnames, vons, surnames, initials, juniors, options
+ if expand_authors and find(author,"\\btxcmd") then
+ author = prerollcmdstring(author)
+ end
local split = lpegmatch(commasplitter,author)
local n = #split
detail = {
@@ -151,8 +159,11 @@ local function splitauthor(author,justsplit)
if n == 1 then
-- {First Middle von Last}
local words = lpegmatch(spacesplitter,author)
- firstnames, vons, surnames = { }, { }, { }
- local i, n = 1, #words
+ local i = 1
+ local n = #words
+ firstnames = { }
+ vons = { }
+ surnames = { }
while i <= n do
local w = words[i]
if is_upper(w) then
@@ -190,9 +201,12 @@ local function splitauthor(author,justsplit)
elseif n == 2 then
-- {Last, First}
-- {von Last, First}
- firstnames, vons, surnames = { }, { }, { }
local words = lpegmatch(spacesplitter,split[1])
- local i, n = 1, #words
+ local i = 1
+ local n = #words
+ firstnames = { }
+ vons = { }
+ surnames = { }
while i <= n do
local w = words[i]
if is_upper(w) then
@@ -202,21 +216,25 @@ local function splitauthor(author,justsplit)
end
end
while i <= n do
- surnames[#surnames+1], i = words[i], i + 1
+ surnames[#surnames+1] = words[i]
+ i = i + 1
end
--
local words = lpegmatch(spacesplitter,split[2])
- local i, n = 1, #words
+ local i = 1
+ local n = #words
while i <= n do
local w = words[i]
if is_upper(w) then
- firstnames[#firstnames+1], i = w, i + 1
+ firstnames[#firstnames+1] = w
+ i = i + 1
else
break
end
end
while i <= n do
- vons[#vons+1], i = words[i], i + 1
+ vons[#vons+1] = words[i]
+ i = i + 1
end
if surnames and firstnames and #surnames == 0 then
-- safeguard
@@ -308,12 +326,14 @@ local function the_initials(initials,symbol,connector)
if not connector then
connector = "-"
end
- local result, r = { }, 0
+ local result = { }
+ local r = 0
for i=1,#initials do
local initial = initials[i]
if type(initial) == "table" then
-- J.-J.
- local set, s = { }, 0
+ local set = { }
+ local s = 0
for i=1,#initial do
if i > 1 then
s = s + 1 ; set[s] = connector
@@ -825,8 +845,10 @@ local p_clean = Cs ( (
+ lpeg.patterns.utf8character
)^1)
+-- Probabbly more robust is a two pass approach.
+
authorhashers.short = function(authors)
- -- a short is a real dumb hardcodes kind of tag and we only support
+ -- a short is a real dumb hardcoded kind of tag and we only support
-- this one because some users might expect it, not because it makes
-- sense
if type(authors) == "table" then
diff --git a/tex/context/base/mkiv/publ-dat.lua b/tex/context/base/mkiv/publ-dat.lua
index 310df82f3..f09e97a8d 100644
--- a/tex/context/base/mkiv/publ-dat.lua
+++ b/tex/context/base/mkiv/publ-dat.lua
@@ -22,6 +22,10 @@ if not characters then
dofile(resolvers.findfile("char-tex.lua"))
end
+if not utilities.sequencers then
+ dofile(resolvers.findfile("util-seq.lua"))
+end
+
local lower, find, sub = string.lower, string.find, string.sub
local concat, copy, tohash = table.concat, table.copy, table.tohash
local next, type, rawget, tonumber = next, type, rawget, tonumber
@@ -30,7 +34,7 @@ local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local textoutf = characters and characters.tex.toutf
local settings_to_hash, settings_to_array = utilities.parsers.settings_to_hash, utilities.parsers.settings_to_array
local formatters = string.formatters
-local sortedkeys, sortedhash, keys = table.sortedkeys, table.sortedhash, table.keys
+local sortedkeys, sortedhash, keys, sort = table.sortedkeys, table.sortedhash, table.keys, table.sort
local xmlcollected, xmltext, xmlconvert = xml.collected, xml.text, xml.convert
local setmetatableindex = table.setmetatableindex
@@ -439,7 +443,7 @@ do
----- command = P("\\") * (Carg(1) * C(R("az","AZ")^1) * space^0 / function(list,c) list[c] = (list[c] or 0) + 1 return "btxcmd{" .. c .. "}" end)
local command = P("\\") * (Carg(1) * C(csletter^1) * space^0 / function(list,c) list[c] = (list[c] or 0) + 1 return "btxcmd{" .. c .. "}" end)
local whatever = P("\\") * P(" ")^1 / " "
- + P("\\") * ( P("hbox") + P("raise") ) -- bah
+ ----- + P("\\") * ( P("hbox") + P("raise") ) -- bah -- no longer
local somemath = P("$") * ((1-P("$"))^1) * P("$") -- let's not assume nested math
----- character = lpegpatterns.utf8character
local any = P(1)
@@ -482,6 +486,8 @@ do
local tags = table.setmetatableindex("table")
+ local indirectcrossrefs = true
+
local function do_definition(category,tag,tab,dataset)
publicationsstats.nofdefinitions = publicationsstats.nofdefinitions + 1
if tag == "" then
@@ -529,11 +535,23 @@ do
value = lpegmatch(filter_2,value,1,dataset.commands) -- we need to start at 1 for { }
end
if normalized == "crossref" then
- local parent = luadata[value]
- if parent then
- setmetatableindex(entries,parent)
+ if indirectcrossrefs then
+ setmetatableindex(entries,function(t,k)
+ local parent = rawget(luadata,value)
+ if parent == entries then
+ report_duplicates("bad parent %a for %a in dataset %s",value,hashtag,dataset.name)
+ setmetatableindex(entries,nil)
+ return entries
+ elseif parent then
+ setmetatableindex(entries,parent)
+ return entries[k]
+ else
+ report_duplicates("no valid parent %a for %a in dataset %s",value,hashtag,dataset.name)
+ setmetatableindex(entries,nil)
+ end
+ end)
else
- -- warning
+ dataset.nofcrossrefs = dataset.nofcrossrefs +1
end
end
entries[normalized] = value
@@ -640,16 +658,17 @@ do
local somevalue = d_value + b_value + s_value + r_value + n_value + e_value
local value = Cs((somevalue * ((spacing * hash * spacing)/"" * somevalue)^0))
- local stripper = lpegpatterns.stripper
- value = value / function(s) return lpegmatch(stripper,s) end
+ local stripper = lpegpatterns.collapser
+ local stripped = value / function(s) return lpegmatch(stripper,s) end
local forget = percent^1 * (1-lineending)^0
local spacing = spacing * forget^0 * spacing
- local assignment = spacing * key * spacing * equal * spacing * value * spacing
+ local replacement= spacing * key * spacing * equal * spacing * value * spacing
+ local assignment = spacing * key * spacing * equal * spacing * stripped * spacing
local definition = category * spacing * left * spacing * tag * spacing * comma * Ct((assignment * comma^0)^0) * spacing * right * Carg(1) / do_definition
local crapword = C((1-space-left)^1)
- local shortcut = Cmt(crapword,function(_,p,s) return lower(s) == "string" and p end) * spacing * left * ((assignment * Carg(1))/do_shortcut * comma^0)^0 * spacing * right
+ local shortcut = Cmt(crapword,function(_,p,s) return lower(s) == "string" and p end) * spacing * left * ((replacement * Carg(1))/do_shortcut * comma^0)^0 * spacing * right
local comment = Cmt(crapword,function(_,p,s) return lower(s) == "comment" and p end) * spacing * lpegpatterns.argument * Carg(1) / do_comment
local casecrap = #S("sScC") * (shortcut + comment)
@@ -682,12 +701,37 @@ do
statistics.starttiming(publications)
publicationsstats.nofbytes = publicationsstats.nofbytes + size
current.nofbytes = current.nofbytes + size
+ current.nofcrossrefs = 0
if source then
table.insert(current.sources, { filename = source, checksum = md5.HEX(content) })
current.loaded[source] = kind or true
end
- current.newtags = #current.luadata > 0 and { } or current.newtags
+ local luadata = current.luadata
+ current.newtags = #luadata > 0 and { } or current.newtags
lpegmatch(bibtotable,content or "",1,current)
+ if current.nofcrossrefs > 0 then
+ for tag, entries in next, luadata do
+ local value = entries.crossref
+ if value then
+ local parent = luadata[value]
+ if parent == entries then
+ report_duplicates("bad parent %a for %a in dataset %s",value,hashtag,dataset.name)
+ elseif parent then
+ local t = { }
+ for k, v in next, parent do
+ if not entries[k] then
+ entries[k] = v
+ t[#t+1] = k
+ end
+ end
+ sort(t)
+ entries.inherited = concat(t,",")
+ else
+ report_duplicates("no valid parent %a for %a in dataset %s",value,hashtag,dataset.name)
+ end
+ end
+ end
+ end
statistics.stoptiming(publications)
end
@@ -708,22 +752,27 @@ do
local compact = false -- can be a directive but then we also need to deal with newlines ... not now
- function publications.converttoxml(dataset,nice,dontstore,usedonly,subset) -- we have fields !
+ function publications.converttoxml(dataset,nice,dontstore,usedonly,subset,noversion,rawtoo) -- we have fields !
local current = datasets[dataset]
local luadata = subset or (current and current.luadata)
if luadata then
statistics.starttiming(publications)
--
local result, r, n = { }, 0, 0
- local usedonly = usedonly and publications.usedentries()
+ if usedonly then
+ usedonly = publications.usedentries()
+ usedonly = usedonly[current.name]
+ end
--
r = r + 1 ; result[r] = "<?xml version='1.0' standalone='yes'?>"
- r = r + 1 ; result[r] = "<bibtex>"
+ r = r + 1 ; result[r] = formatters["<bibtex dataset='%s'>"](current.name)
--
if nice then -- will be default
local f_entry_start = formatters[" <entry tag='%s' category='%s' index='%s'>"]
local s_entry_stop = " </entry>"
local f_field = formatters[" <field name='%s'>%s</field>"]
+ local f_cdata = formatters[" <field name='rawbibtex'><![CDATA[%s]]></field>"]
+
for tag, entry in sortedhash(luadata) do
if not usedonly or usedonly[tag] then
r = r + 1 ; result[r] = f_entry_start(tag,entry.category,entry.index)
@@ -737,6 +786,11 @@ do
end
end
end
+ if rawtoo then
+ local s = publications.savers.bib(current,false,{ [tag] = entry })
+ s = utilities.strings.striplines(s,"prune and collapse")
+ r = r + 1 ; result[r] = f_cdata(s)
+ end
r = r + 1 ; result[r] = s_entry_stop
n = n + 1
end
@@ -766,7 +820,7 @@ do
--
r = r + 1 ; result[r] = "</bibtex>"
--
- result = concat(result,nice and "\n" or nil)
+ result = concat(result,nice and "\n" or nil,noversion and 2 or 1,#result)
--
if dontstore then
-- indeed
@@ -1084,7 +1138,7 @@ do
\ifdefined\btxcmd
% we're probably in context
\else
- \def\btxcmd#1{\csname#1\endcsname}
+ \def\btxcmd#1{\begincsname#1\endcsname}
\fi
}
@@ -1094,8 +1148,8 @@ do
local f_start = formatters["@%s{%s,\n"]
local f_field = formatters[" %s = {%s},\n"]
local s_stop = "}\n\n"
- local result = { s_preamble }
- local n, r = 0, 1
+ local result = { }
+ local n, r = 0, 0
for tag, data in sortedhash(tobesaved) do
r = r + 1 ; result[r] = f_start(data.category or "article",tag)
for key, value in sortedhash(data) do
@@ -1106,8 +1160,16 @@ do
r = r + 1 ; result[r] = s_stop
n = n + 1
end
- report("%s entries from dataset %a saved in %a",n,dataset,filename)
- io.savedata(filename,concat(result))
+ result = concat(result)
+ if find(result,"\\btxcmd") then
+ result = s_preamble .. result
+ end
+ if filename then
+ report("%s entries from dataset %a saved in %a",n,dataset,filename)
+ io.savedata(filename,result)
+ else
+ return result
+ end
end
function savers.lua(dataset,filename,tobesaved)
@@ -1127,8 +1189,8 @@ do
table.save(filename,list)
end
- function savers.xml(dataset,filename,tobesaved)
- local result, n = publications.converttoxml(dataset,true,true,false,tobesaved)
+ function savers.xml(dataset,filename,tobesaved,rawtoo)
+ local result, n = publications.converttoxml(dataset,true,true,false,tobesaved,false,rawtoo)
report("%s entries from dataset %a saved in %a",n,dataset,filename)
io.savedata(filename,result)
end
@@ -1175,6 +1237,8 @@ do
return dataset
end
+ publications.savers = savers
+
if implement then
implement {
@@ -1248,3 +1312,18 @@ do
writers.pagenumber = writers.range
end
+
+if implement then
+
+ implement {
+ name = "btxshortcut",
+ arguments = "2 strings",
+ actions = function(instance,key)
+ local d = publications.datasets[instance]
+ context(d and d.shortcuts[key] or "?")
+ end,
+ }
+
+end
+
+-- inspect(publications.load { filename = "e:/tmp/oeps.bib" })
diff --git a/tex/context/base/mkiv/publ-imp-apa.mkvi b/tex/context/base/mkiv/publ-imp-apa.mkvi
index cd78a8799..160cc4522 100644
--- a/tex/context/base/mkiv/publ-imp-apa.mkvi
+++ b/tex/context/base/mkiv/publ-imp-apa.mkvi
@@ -432,8 +432,44 @@
\c!style=\v!italic]
\definebtx
+ [apa:\s!cite:subtitle]
+ [apa:\s!cite:title]
+
+\definebtx
+ [apa:\s!cite:booktitle]
+ [apa:\s!cite:title]
+
+\definebtx
+ [apa:\s!cite:subbooktitle]
[apa:\s!cite:booktitle]
+
+% Will these get used?
+
+\definebtx
+ [apa:\s!cite:title:inbook]
[apa:\s!cite:title]
+ [\c!style=] % not italic
+
+\definebtx
+ [apa:\s!cite:title:incollection]
+ [apa:\s!cite:title:inbook]
+
+\definebtx
+ [apa:\s!cite:title:inproceedings]
+ [apa:\s!cite:title:inbook]
+
+\definebtx
+ [apa:\s!cite:subtitle:inbook]
+ [apa:\s!cite:title:inbook]
+
+\definebtx
+ [apa:\s!cite:subtitle:incollection]
+ [apa:\s!cite:title:incollection]
+
+\definebtx
+ [apa:\s!cite:subtitle:inproceedings]
+ [apa:\s!cite:title:inproceedings]
+
\definebtx
[apa:\s!cite:tag]
@@ -441,7 +477,6 @@
[\c!left={[},
\c!right={]}]
-
\definebtx
[apa:\s!cite:index]
[apa:\s!cite]
@@ -679,6 +714,50 @@
\fastsetup{\s!btx:\s!cite:author:years}
\stopsetups
+% these setups need to be explicitly defined in order to get cite rendering
+
+\startsetups \s!btx:apa:\s!cite:organization
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+
+\startsetups \s!btx:apa:\s!cite:subtitle
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+
+\startsetups \s!btx:apa:\s!cite:booktitle
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+
+\startsetups \s!btx:apa:\s!cite:subbooktitle
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+
+% are these needed?
+
+\startsetups \s!btx:apa:\s!cite:title:inbook
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+
+\startsetups \s!btx:apa:\s!cite:title:incollection
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+
+\startsetups \s!btx:apa:\s!cite:title:inproceedings
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+
+\startsetups \s!btx:apa:\s!cite:subtitle:inbook
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+
+\startsetups \s!btx:apa:\s!cite:subtitle:incollection
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+
+\startsetups \s!btx:apa:\s!cite:subtitle:inproceedings
+ \fastsetup{\s!btx:\s!cite:normal}
+\stopsetups
+
% used in publ-imp-page.mkvi
\startsetups btx:apa:list:page-or-pages
@@ -797,7 +876,7 @@
% A book might have an editor AND an author
\doif {\currentbtxcategory} {book} {
\doifnot {\btxfoundname{author}} {editor} {
- \btxdoif {ineditor} { % ineditor authorconversion
+ \btxdoif {ineditor} { % ineditor specific authorconversion
\btxleftparenthesis
\btxflush{ineditor}
\btxcomma
@@ -973,11 +1052,11 @@
\starttexdefinition unexpanded btx:apa:editor-in
\btxdoif {booktitle} {
\btxlabeltext{In}
+ \btxspace
\doifnot {\btxfoundname{author}} {editor} {
- \btxspace
\texdefinition{btx:apa:author-or-editor} {ineditor}
+ \btxcomma
}
- \btxspace
\texdefinition{btx:apa:composed-title}{booktitle}
\btxperiod
}
diff --git a/tex/context/base/mkiv/publ-imp-cite.mkvi b/tex/context/base/mkiv/publ-imp-cite.mkvi
index 8fe96429d..56af83a1b 100644
--- a/tex/context/base/mkiv/publ-imp-cite.mkvi
+++ b/tex/context/base/mkiv/publ-imp-cite.mkvi
@@ -232,9 +232,6 @@
\startsetups \s!btx:\s!cite:pages
\fastsetup{\s!btx:\s!cite:range}
\stopsetups
-\startsetups \s!btx:\s!cite:organization
- \fastsetup{\s!btx:\s!cite:range}
-\stopsetups
% is the next one used?
% Yes, bibtex is a mess and one can have pages or sometimes page
diff --git a/tex/context/base/mkiv/publ-inc.lua b/tex/context/base/mkiv/publ-inc.lua
new file mode 100644
index 000000000..9231be3c1
--- /dev/null
+++ b/tex/context/base/mkiv/publ-inc.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['publ-inc'] = {
+ version = 1.001,
+ comment = "this module part of publication support",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local fullstrip = string.fullstrip
+local datasets, savers = publications.datasets, publications.savers
+local assignbuffer = buffers.assign
+
+interfaces.implement {
+ name = "btxentrytobuffer",
+ arguments = "3 strings",
+ actions = function(dataset,tag,target)
+ local d = datasets[dataset]
+ if d then
+ d = d.luadata[tag]
+ end
+ if d then
+ d = fullstrip(savers.bib(dataset,false,{ [tag] = d }))
+ end
+ assignbuffer(target,d or "")
+ end
+}
diff --git a/tex/context/base/mkiv/publ-inc.mkiv b/tex/context/base/mkiv/publ-inc.mkiv
new file mode 100644
index 000000000..c1728f44a
--- /dev/null
+++ b/tex/context/base/mkiv/publ-inc.mkiv
@@ -0,0 +1,63 @@
+%D \module
+%D [ file=publ-inc,
+%D version=2018.06.23,
+%D title=\CONTEXT\ Publication Macros,
+%D subtitle=XML inclusion,
+%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 Publication Macros / XML inclusion}
+
+\registerctxluafile{publ-inc}{}
+
+%D A teaser for Alan.
+
+\unprotect
+
+\definesymbol[btxattachment][{\infofont\darkred btx}]
+\definesymbol[btxcomment] [{\infofont\darkblue btx}]
+
+\unexpanded\def\btx_add_blob#1#2%
+ {\relax
+ \clf_btxentrytobuffer{\currentbtxdataset}{\currentbtxtag}{temp-btx-export}%
+ #2%
+ [\c!symbol=#1,%
+ \c!space=\v!yes,
+ \c!buffer=temp-btx-export,%
+ \c!name={\currentbtxtag.bib}]%
+ \relax}
+
+\unexpanded\def\btxattach
+ {\iftrialtypesetting \else \ifexporting \iflocation
+ \dostarttagged\t!ignore\empty
+ \btx_add_blob{btxattachment}\attachment
+ \dostoptagged
+ \fi \fi \fi}
+
+\unexpanded\def\btxcomment
+ {\iftrialtypesetting \else \ifexporting \iflocation
+ \dostarttagged\t!ignore\empty
+ \btx_add_blob{btxcomment}\comment
+ \dostoptagged
+ \fi \fi \fi}
+
+%D This kind of feature creep is not yet configurable, nor documented.
+
+\unexpanded\def\btxaddsource
+ {\iftrialtypesetting \else \ifexporting \iflocation
+ \dostarttagged\t!ignore\empty
+ \llap{%
+ \btx_add_blob{btxattachment}\attachment
+ \quad
+ \btx_add_blob{btxcomment}\comment
+ \hskip\leftmargindistance
+ }%
+ \dostoptagged
+ \fi \fi \fi}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/publ-ini.lua b/tex/context/base/mkiv/publ-ini.lua
index 9dfeda168..f62352f07 100644
--- a/tex/context/base/mkiv/publ-ini.lua
+++ b/tex/context/base/mkiv/publ-ini.lua
@@ -32,7 +32,7 @@ local sortedkeys, sortedhash = table.sortedkeys, table.sortedhash
local setmetatableindex = table.setmetatableindex
local lpegmatch = lpeg.match
local P, S, C, Ct, Cs, R, Carg = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.R, lpeg.Carg
-local upper = utf.upper
+local upper = characters.upper
local report = logs.reporter("publications")
local report_cite = logs.reporter("publications","cite")
@@ -229,9 +229,9 @@ logs.registerfinalactions(function()
logs.startfilelogging(report,"used btx commands")
done = true
end
- if isdefined[command] then
+ if isdefined(command) then
report("%-20s %-20s % 5i %s",name,command,n,"known")
- elseif isdefined[upper(command)] then
+ elseif isdefined(upper(command)) then
report("%-20s %-20s % 5i %s",name,command,n,"KNOWN")
else
report("%-20s %-20s % 5i %s",name,command,n,"unknown")
@@ -246,7 +246,7 @@ logs.registerfinalactions(function()
logs.starterrorlogging(report,"unknown btx commands")
for name, dataset in sortedhash(datasets) do
for command, n in sortedhash(dataset.commands) do
- if not isdefined[command] and not isdefined[upper(command)] then
+ if not isdefined(command) and not isdefined(upper(command)) then
report("%-20s %-20s % 5i %s",name,command,n,"unknown")
end
end
@@ -1065,14 +1065,17 @@ do
-- maybe not redo when already done
local function shortsorter(a,b)
- local ay, by = a[2], b[2] -- year
+ local ay = a[2] -- year
+ local by = b[2] -- year
if ay ~= by then
return ay < by
end
- local ay, by = a[3], b[3] -- suffix
+ local ay = a[3] -- suffix
+ local by = b[3] -- suffix
if ay ~= by then
-- bah, bah, bah
- local an, bn = tonumber(ay), tonumber(by)
+ local an = tonumber(ay)
+ local bn = tonumber(by)
if an and bn then
return an < bn
else
@@ -2023,7 +2026,8 @@ do
for i=1,nofranges do
local r = ranges[i]
ctx_btxsetconcat(concatstate(i,nofranges))
- local first, last = r[1], r[2]
+ local first = r[1]
+ local last = r[2]
ctx_btxsetfirstinternal(first[2].internal)
ctx_btxsetfirstpage(first[1])
if last then
@@ -2044,7 +2048,8 @@ do
}
local function identical(a,b)
- local na, nb = #a, #b
+ local na = #a
+ local nb = #b
if na ~= nb then
return false
end
@@ -2056,7 +2061,8 @@ do
end
return true
end
- local ha, hb = a.hash, b.hash
+ local ha = a.hash
+ local hb = b.hash
if ha then
return ha == hb
end
@@ -3456,3 +3462,20 @@ do
}
end
+
+do
+
+ local btxstring = ""
+
+ implement {
+ name = "btxcmdstring",
+ actions = function() if btxstring ~= "" then context(btxstring) end end,
+ }
+
+ function publications.prerollcmdstring(str)
+ btxstring = str or ""
+ tex.runtoks("t_btx_cmd")
+ return nodes.toutf(tex.getbox("b_btx_cmd").list) or str
+ end
+
+end
diff --git a/tex/context/base/mkiv/publ-ini.mkiv b/tex/context/base/mkiv/publ-ini.mkiv
index 9f970547d..ead46929d 100644
--- a/tex/context/base/mkiv/publ-ini.mkiv
+++ b/tex/context/base/mkiv/publ-ini.mkiv
@@ -107,23 +107,27 @@
%D to split between cite and list here as it only complicates matters (timing) and is
%D not clear either.
-\let\currentbtxspecification\empty
+\let\currentbtxspecification \empty
+\let\currentbtxspecificationfallback\empty
+
+\installmacrostack\currentbtxspecification
+\installmacrostack\currentbtxspecificationfallback
\unexpanded\def\startbtxrenderingdefinitions[#1]%
{\unprotect
- \pushmacro\currentbtxspecification
+ \push_macro_currentbtxspecification
\edef\currentbtxspecification{#1}}
\unexpanded\def\stopbtxrenderingdefinitions
- {\popmacro\currentbtxspecification
+ {\pop_macro_currentbtxspecification
\protect}
\unexpanded\def\loadbtxdefinitionfile [#1]{\clf_btxloaddefinitionfile {#1}}
\unexpanded\def\loadbtxreplacementfile[#1]{\clf_btxloadreplacementfile{#1}}
\unexpanded\def\publ_specification_push#1%
- {\pushmacro\currentbtxspecification
- \pushmacro\currentbtxspecificationfallback
+ {\push_macro_currentbtxspecification
+ \push_macro_currentbtxspecificationfallback
\edef\currentbtxspecification{#1}%
\edef\currentbtxspecificationfallback{\namedbtxparameter\currentbtxspecification\c!default}%
\ifx\currentbtxspecificationfallback\currentbtxspecification
@@ -132,8 +136,8 @@
\clf_btxsetspecification{\currentbtxspecification}}
\unexpanded\def\publ_specification_pop
- {\popmacro\currentbtxspecificationfallback
- \popmacro\currentbtxspecification
+ {\pop_macro_currentbtxspecificationfallback
+ \pop_macro_currentbtxspecification
\clf_btxsetspecification{\currentbtxspecification}}
\unexpanded\def\publ_specification_set#1% beware: is global
@@ -223,9 +227,6 @@
\installcommandhandler \??btxregister {btxregister} \??btxregister
\installcommandhandler \??btxrendering {btxrendering} \??btxrendering
-\let\currentbtxcitealternative \empty
-\let\currentbtxspecificationfallback\empty
-
\unexpanded\def\setbtxparameterset#1#2%
{\edef\currentbtx
{\ifcsname\??btx\currentbtxspecification:#1:#2:\s!parent\endcsname
@@ -333,6 +334,11 @@
\expandafter\publ_command_nop
\fi{#1}}
+\newtoks\t_btx_cmd
+\newbox \b_btx_cmd
+
+\t_btx_cmd{\global\setbox\b_btx_cmd\hpack{\clf_btxcmdstring}}
+
\let\btxcmd\btxcommand
\def\publ_command_yes#1%
@@ -341,10 +347,10 @@
\def\publ_command_nop#1%
{\ifcsname#1\endcsname
\showmessage\m!publications{10}{#1,#1}%
- \global\expandafter\let\csname\??btxcommand#1\expandafter\endcsname\csname#1\endcsname
+ \expandafter\glet\csname\??btxcommand#1\expandafter\endcsname\csname#1\endcsname
\else\ifcsname\utfupper{#1}\endcsname
\showmessage\m!publications{10}{#1}{\utfupper{#1}}%
- \global\expandafter\let\csname\??btxcommand#1\expandafter\endcsname\csname\utfupper{#1}\endcsname
+ \expandafter\glet\csname\??btxcommand#1\expandafter\endcsname\csname\utfupper{#1}\endcsname
\else
\showmessage\m!publications{11}{#1}%
\setugvalue{\??btxcommand#1}{\underbar{\tttf#1}}%
@@ -385,6 +391,12 @@
\let\btxsetup\fastsetup
+\def\btxfield #1{\dostarttagged\t!pubfld{#1}\clf_btxfield {\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged}
+\def\btxdetail #1{\dostarttagged\t!pubfld{#1}\clf_btxdetail{\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged}
+\def\btxflush #1{\dostarttagged\t!pubfld{#1}\clf_btxflush {\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged}
+\def\btxdirect #1{\dostarttagged\t!pubfld{#1}\clf_btxdirect{\currentbtxdataset}{\currentbtxtag}{#1}\dostoptagged}
+%def\btxauthorfield#1{\dostarttagged\t!pubfld{#1}\clf_btxauthorfield \currentbtxauthorindex{#1}\dostoptagged}
+
%D How complex will we go? Can we assume that e.g. an apa style will not be mixed
%D with another one? I think this assumption is okay. For manuals we might want to
%D mix but we can work around it.
@@ -629,11 +641,13 @@
\unexpanded\def\btxnumberingsetup#1%
{\begingroup
+ \dostarttagged\t!listtag\empty
\setbtxparameterset{\c!list:\s!numbering}\currentbtxnumbering % brrrr \setbtxlist
\btxparameter\c!left
% \btxparameter\c!command{\publ_fast_setup\plusthree{\s!list:\s!numbering}{#1}}%
\publ_fast_setup\plusthree{\s!list:\s!numbering}{#1}%
\btxparameter\c!right
+ \dostoptagged
\endgroup
\btx_reset_numbering} % probably not needed
@@ -655,21 +669,34 @@
\def\btx_entry_inject_list_text
{\publ_fast_setup\plusfour\s!list\s!text}
+\ifdefined\dotagpublication \else \let\dotagpublication \gobbletwoarguments \fi
+
\unexpanded\def\btx_entry_inject
{\begingroup
+ \dostarttagged\t!publication\empty
+ \dotagpublication\currentbtxdataset\currentbtxtag
\redoconvertfont % see (**) in strc-lst, this will become an configuration option
\edef\currentbtxcategory{\btxfield{category}}%
\ignorespaces
\ifconditional\c_btx_list_texts
+ \dostarttagged\t!listtext\s!left
\currentbtxbefore
+ \dostoptagged
\fi
+ %\dostarttagged\t!listcontent\empty
\btx_entry_inject_list_text
+ %\dostoptagged
\ifconditional\c_btx_list_pages
+ \dostarttagged\t!listpage\empty
\btx_entry_inject_pages
+ \dostoptagged
\fi
\ifconditional\c_btx_list_texts
+ \dostarttagged\t!listtext\s!right
\currentbtxafter
+ \dostoptagged
\fi
+ \dostoptagged
\endgroup}
\unexpanded\def\btxshowentryinline
@@ -843,6 +870,8 @@
\expandafter\p_command\expandafter{\number\nofbtxlistentries}\relax
\fi
\else
+ \dostarttagged\t!publications\currentbtxrendering
+ \dostarttagged\t!list{btx}%
\startpacked[\v!blank]%
% sorting and so
\clf_btxpreparelistentries{\currentbtxdataset}% could be put in collect
@@ -865,6 +894,8 @@
{\let\currentbtxlistentry\recurselevel
\clf_btxflushlistentry{\currentbtxdataset}\currentbtxlistentry\relax}%
\stoppacked
+ \dostoptagged
+ \dostoptagged
\fi
\btxrenderingparameter\c!after
\fi
@@ -978,8 +1009,10 @@
\strc_lists_apply_renderingsetup}
\def\btx_entry_indeed
- {\btx_list_reference_inject
- \btx_entry_inject}
+ {\dostarttagged\t!listcontent\empty
+ \btx_list_reference_inject
+ \btx_entry_inject
+ \dostoptagged}
\def\btx_page_indeed
{}
@@ -1113,7 +1146,8 @@
\let\btxcitereference\btx_cite_reference_inject
-\let\currentbtxnumbering\empty
+\let\currentbtxnumbering \empty
+\let\currentbtxcitealternative \empty
\appendtoks
\edef\currentbtxnumbering{\btxrenderingparameter\c!numbering}%
@@ -1995,4 +2029,15 @@
\fetchruntimecommand \showbtxfields \f!publ_tra
\fetchruntimecommand \showbtxtables \f!publ_tra
+%D Some potential crap:
+%D
+%D Because I consider this bad data management and a weird mix of languages only one
+%D accessor is provided.
+
+\unexpanded\def\btxshortcut
+ {\dosingleempty\publ_shortcut}
+
+\def\publ_shortcut[#1]#2%
+ {\clf_btxshortcut{\iffirstargument#1\else\s!default\fi}{#2}}
+
\protect
diff --git a/tex/context/base/mkiv/scrn-bar.mkvi b/tex/context/base/mkiv/scrn-bar.mkvi
index 7634398f8..0c320cd03 100644
--- a/tex/context/base/mkiv/scrn-bar.mkvi
+++ b/tex/context/base/mkiv/scrn-bar.mkvi
@@ -138,7 +138,7 @@
\setbox2\hbox{\inheritedinteractionbarframed{\symbol[\interactionparameter\c!symbolset][\v!previouspage]}}%
\scratchheight\ht2 % needed because we default to nothing
\letinteractionbarparameter\c!strut\v!no
- \letinteractionparameter\c!width\zeropoint
+ % \letinteractionparameter\c!width\zeropoint
\scratchcounterone\zerocount % new, was 1
\processallactionsinset
[#list]
diff --git a/tex/context/base/mkiv/scrn-but.mkvi b/tex/context/base/mkiv/scrn-but.mkvi
index 8bbd6eeda..87af29cfb 100644
--- a/tex/context/base/mkiv/scrn-but.mkvi
+++ b/tex/context/base/mkiv/scrn-but.mkvi
@@ -11,20 +11,16 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-% \restorestandardblank
-% better namespace for pos
-
\writestatus{loading}{ConTeXt Screen Macros / Buttons}
\registerctxluafile{scrn-but}{}
\unprotect
-%D Buttons are just what their names says: things that can be
-%D clicked (pushed) on. They are similar to \type{\goto},
-%D except that the text argument is not interpreted.
-%D Furthermore one can apply anything to them that can be done
-%D with \type{\framed}.
+%D Buttons are just what their names says: things that can be clicked (pushed) on.
+%D They are similar to \type{\goto}, except that the text argument is not
+%D interpreted. Furthermore one can apply anything to them that can be done with
+%D \type {\framed}.
%D
%D \startbuffer
%D \button[width=3cm,height=1.5cm]{Exit}[ExitViewer]
@@ -119,8 +115,8 @@
%D \overlaybutton[reference]
%D \stoptyping
%D
-%D This command can be used to define overlays an/or can be
-%D used in the whatevertext areas, like:
+%D This command can be used to define overlays an/or can be used in the whatevertext
+%D areas, like:
%D
%D \starttyping
%D \defineoverlay[PrevPage][\overlaybutton{PrevPage}]
@@ -128,8 +124,7 @@
%D \setuptexttexts[\overlaybutton{NextPage}]
%D \stoptyping
%D
-%D For practical reasons, this macro accepts square brackets
-%D as well as braces.
+%D For practical reasons, this macro accepts square brackets as well as braces.
\unexpanded\def\overlaybutton
{\dosingleempty\scrn_button_overlay}
diff --git a/tex/context/base/mkiv/scrn-fld.mkvi b/tex/context/base/mkiv/scrn-fld.mkvi
index dec334209..7710a32dc 100644
--- a/tex/context/base/mkiv/scrn-fld.mkvi
+++ b/tex/context/base/mkiv/scrn-fld.mkvi
@@ -480,7 +480,7 @@
\let\resetfields\relax
-\def\scrn_field_load_scripts{\useJSscripts[fld]\globallet\scrn_field_load_scripts\relax}
+\def\scrn_field_load_scripts{\useJSscripts[fld]\glet\scrn_field_load_scripts\relax}
\newconditional\fieldlabelshown
\newconditional\fieldframeshown
@@ -627,11 +627,13 @@
%D Common stuff (obsolete)
+
\newcount\c_scrn_field_system_n
-\def\nextsystemfield
- {\global\advance\c_scrn_field_system_n\plusone
- \def\currentsystemfield{sys::\number\c_scrn_field_system_n}}
+\def\currentsystemfield{sys::\number\c_scrn_field_system_n}
+
+\unexpanded\def\nextsystemfield
+ {\global\advance\c_scrn_field_system_n\plusone}
%D \CONTEXT\ had tooltips right from the moment that it
%D supported fields. Due to the at that moment somewhat
@@ -754,7 +756,8 @@
{\ifcsname\??fieldstack#tag\endcsname
% already done
\else
- \setgvalue{\??fieldstack#tag}{\scrn_fieldstack_construct[#tag][#symbols][#settings]}%
+ %setgvalue{\??fieldstack#tag}{\scrn_fieldstack_construct[#tag][#symbols][#settings]}%
+ \setxvalue{\??fieldstack#tag}{\scrn_fieldstack_construct[#tag][#symbols][\normalunexpanded{#settings}]}%
\fi}
\unexpanded\def\fieldstack
@@ -768,26 +771,28 @@
\newbox\b_scrn_fieldstack_box
+\definesymbol[\s!empty][]
+
\def\scrn_fieldstack_add#tag#settings#symbol%
{\advance\scratchcounter\plusone
\edef\currentfieldstackname{#tag:\number\scratchcounter}%
\ifnum\scratchcounter=\fieldcategoryparameter\c!start\relax
- \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\empty},\c!default={#symbol}]%
+ \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\s!empty},\c!default={#symbol}]%
\else
- \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\empty},\c!default=]%
+ \definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\s!empty},\c!default=\s!empty]%
\fi
\setbox\b_scrn_fieldstack_box\hbox{\symbol[#symbol]}%
\setcollector
[fieldstack]
{\fieldbody
[\currentfieldstackname]
- [\c!option=\v!readonly,
+ [\c!option={\v!readonly},
\c!width=\wd\b_scrn_fieldstack_box,
\c!height=\ht\b_scrn_fieldstack_box,
\c!depth=\dp\b_scrn_fieldstack_box,
#settings]}}
-\def\scrn_fieldstack_construct[#tag][#symbols][#settings]% start=n, 0 == leeg
+\unexpanded\def\scrn_fieldstack_construct[#tag][#symbols][#settings]% start=n, 0 == leeg
{\iflocation
\dontleavehmode
\begingroup
@@ -822,21 +827,56 @@
\unexpanded\def\overlayrollbutton
{\dodoubleargument\scrn_rollbutton_overlay}
-\def\scrn_rollbutton_overlay[#regionin][#regionout]%
+\unexpanded\def\scrn_rollbutton_overlay[#regionin][#regionout]%
+ {\iffirstargument
+ \scrn_rollbutton_overlay_indeed[#regionin][#regionout]%
+ \else
+ \expandafter\scrn_rollbutton_overlay_indeed
+ \fi}
+
+% \def\scrn_rollbutton_overlay_indeed#regionin#regionout%
+% {\iflocation
+% \bgroup
+% \global\advance\c_scrn_rollbutton_n\plusone
+% \definesymbol
+% [rollbutton:\number\c_scrn_rollbutton_n]
+% [{\framed[\c!frame=\v!off,\c!width=\overlaywidth,\c!height=\overlayheight]{}}]%
+% \definefieldbody
+% [rollbutton:\number\c_scrn_rollbutton_n]
+% [\c!type=push,
+% \c!regionin={#regionin},
+% \c!regionout={#regionout},
+% \c!values=\currentsystemfield,
+% \c!default=\currentsystemfield]%
+% \fitfield[\currentsystemfield]%
+% \egroup
+% \fi}
+
+\def\scrn_rollbutton_overlay_indeed#regionin#regionout%
{\iflocation
\bgroup
- \global\advance\c_scrn_rollbutton_n\plusone
+ \global\advance\c_scrn_rollbutton_n_button\plusone
+ \global\advance\c_scrn_rollbutton_n_symbol\plusone
\definesymbol
- [rollbutton:\number\c_scrn_rollbutton_n]
+ [rollsymbol:\number\c_scrn_rollbutton_n_symbol]
[{\framed[\c!frame=\v!off,\c!width=\overlaywidth,\c!height=\overlayheight]{}}]%
- \definefieldbody
- [rollbutton:\number\c_scrn_rollbutton_n]
- [\c!type=push,
- \c!regionin={#regionin},
- \c!regionout={#regionout},
- \c!values=\currentsystemfield,
- \c!default=\currentsystemfield]%
- \fitfield[\currentsystemfield]%
+ % \definefieldbody
+ % [rollbutton:\number\c_scrn_rollbutton_n_button]
+ % [\c!type=push,
+ % \c!values=rollsymbol:\number\c_scrn_rollbutton_n_symbol,
+ % \c!default=rollsymbol:\number\c_scrn_rollbutton_n_symbol]%
+ % \fitfield
+ % [rollbutton:\number\c_scrn_rollbutton_n_button]%
+ % [\c!regionin={#regionin},
+ % \c!regionout={#regionout}]%
+ %
+ \definefield
+ [rollbutton:\number\c_scrn_rollbutton_n_button][push][rollbutton]
+ [rollsymbol:\number\c_scrn_rollbutton_n_symbol]%
+ \fitfield
+ [rollbutton:\number\c_scrn_rollbutton_n_button]%
+ [\c!regionin={#regionin},\c!regionout={#regionout}]%
+ %
\egroup
\fi}
@@ -914,7 +954,7 @@
%D We plug into the menu system
\unexpanded\def\scrn_menu_psh_start[#reference]#text\stoppsh
- {\starttxt\pushbutton[\currentmenu][#reference]\stoptxt}
+ {\starttxt\pushbutton[\currentinteractionmenu][#reference]\stoptxt}
\unexpanded\def\scrn_menu_psh_direct[#reference]#text\\
{\scrn_menu_psh_start[#reference]\stoprob}
@@ -956,6 +996,8 @@
\newcount\c_scrn_rollbutton_n_button
\newcount\c_scrn_rollbutton_n_symbol
+\def\lastrollbuttonindex{\the\c_scrn_rollbutton_n_button}
+
\unexpanded\def\rollbutton
{\dodoubleempty\scrn_rollbutton}
@@ -973,11 +1015,16 @@
\setbuttonparameter
\usebuttonstyleandcolor}
+\setupfield
+ [rollbutton]
+ [\c!frame=\v!off,
+ \c!offset=\v!overlay]
+
\def\scrn_rollbutton[#tag][#settings]#text[#reference]%
{\dontleavehmode
\bgroup
- \advance\c_scrn_rollbutton_n_button\plusone
- \advance\c_scrn_rollbutton_n_symbol\plusone
+ \global\advance\c_scrn_rollbutton_n_button\plusone
+ \global\advance\c_scrn_rollbutton_n_symbol\plusone
\iffirstargument
\ifsecondargument
\edef\currentinteractionmenu{#tag}%
@@ -994,21 +1041,18 @@
\else
\let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_b
\fi
- % todo: share symbols, tricky since different dimensions
+ % todo: share symbols, tricky since different dimensions (maybe \unique...)
\definesymbol[rollsymbol:\number\c_scrn_rollbutton_n_symbol:n][\scrn_rollbutton_symbol{n}{#text}]%
\definesymbol[rollsymbol:\number\c_scrn_rollbutton_n_symbol:r][\scrn_rollbutton_symbol{r}{#text}]%
\definesymbol[rollsymbol:\number\c_scrn_rollbutton_n_symbol:d][\scrn_rollbutton_symbol{d}{#text}]%
- \setupfield
- [rollbutton]
- [\c!frame=\v!off,
- \c!offset=\v!overlay,
- \c!clickout={#reference}]%
\definefield
[rollbutton:\number\c_scrn_rollbutton_n_button][push][rollbutton]
[rollsymbol:\number\c_scrn_rollbutton_n_symbol:n,%
rollsymbol:\number\c_scrn_rollbutton_n_symbol:r,%
rollsymbol:\number\c_scrn_rollbutton_n_symbol:d]%
- \fitfield[rollbutton:\number\c_scrn_rollbutton_n_button]%
+ \fitfield
+ [rollbutton:\number\c_scrn_rollbutton_n_button]%
+ [\c!clickout={#reference}]%
\egroup}
\unexpanded\def\scrn_rollbutton_symbol_indeed#getparameter#inheritedframed#setparameter#usestyleandcolor#what#text%
@@ -1023,7 +1067,7 @@
%D We plug into the menu system
\unexpanded\def\scrn_menu_rob_start[#reference]#text\stoprob
- {\starttxt\rollbutton[\currentmenu]{\ignorespaces#text\unskip}[#reference]\stoptxt}
+ {\starttxt\rollbutton[\currentinteractionmenu]{\ignorespaces#text\unskip}[#reference]\stoptxt}
\unexpanded\def\scrn_menu_rob_direct[#reference]#text\\
{\scrn_menu_rob_start[#reference]#text\stoprob}
diff --git a/tex/context/base/mkiv/scrn-ini.mkvi b/tex/context/base/mkiv/scrn-ini.mkvi
index e1be43f37..557ceb563 100644
--- a/tex/context/base/mkiv/scrn-ini.mkvi
+++ b/tex/context/base/mkiv/scrn-ini.mkvi
@@ -61,7 +61,7 @@
\to \everyjob
% it makes no sense to create an environment as we will seldom have structured
-% interactionso a general start-stop will do
+% interactions so a general start-stop will do
%
% \appendtoks
% \setuevalue \currentinteraction {\scrn_interaction_direct{\currentinteraction}}%
diff --git a/tex/context/base/mkiv/scrn-pag.mkvi b/tex/context/base/mkiv/scrn-pag.mkvi
index 7695443ad..a3b0a78c6 100644
--- a/tex/context/base/mkiv/scrn-pag.mkvi
+++ b/tex/context/base/mkiv/scrn-pag.mkvi
@@ -188,13 +188,13 @@
\let\scrn_canvas_synchronize_complex\relax
\appendtoks
- \global\let\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed
- \global\let\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed
+ \glet\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed
+ \glet\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed
\to \everysetuplayout
\appendtoks
- \global\let\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed
- \global\let\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed
+ \glet\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed
+ \glet\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed
\to \everysetuplayouttarget
\def\scrn_canvas_synchronize_only
@@ -213,8 +213,8 @@
\def\scrn_canvas_synchronize_simple_indeed
{\scrn_canvas_synchronize_only
- %\global\let\scrn_canvas_synchronize_simple \relax
- \global\let\scrn_canvas_synchronize_complex\relax}
+ %\glet\scrn_canvas_synchronize_simple \relax
+ \glet\scrn_canvas_synchronize_complex\relax}
\def\scrn_canvas_synchronize_complex_indeed
{\scrn_canvas_calculate % otherwise we need to hook it into setuppage etc
@@ -235,8 +235,8 @@
copies \numexpr\interactionscreenparameter\c!copies\relax
print {\interactionscreenparameter\c!print}%
\relax
- %\global\let\scrn_canvas_synchronize_simple \relax
- \global\let\scrn_canvas_synchronize_complex\relax}
+ %\glet\scrn_canvas_synchronize_simple \relax
+ \glet\scrn_canvas_synchronize_complex\relax}
\appendtoks
\begingroup
@@ -262,8 +262,8 @@
\c!option=\v!auto]
\appendtoks
- \global\let\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed
- \global\let\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed
+ \glet\scrn_canvas_synchronize_simple \scrn_canvas_synchronize_simple_indeed
+ \glet\scrn_canvas_synchronize_complex\scrn_canvas_synchronize_complex_indeed
\to \everysetupinteractionscreen
%D Conditional page breaks:
diff --git a/tex/context/base/mkiv/scrn-ref.mkvi b/tex/context/base/mkiv/scrn-ref.mkvi
index bace13312..df395e550 100644
--- a/tex/context/base/mkiv/scrn-ref.mkvi
+++ b/tex/context/base/mkiv/scrn-ref.mkvi
@@ -83,15 +83,15 @@
%D delayed ...
-\def\scrn_reference_enable_references
- {\ifproductionrun
- \clf_enableinteraction % only once anyway
- \glet\scrn_reference_enable_references\relax
- \fi}
-
-\appendtoks
- \scrn_reference_enable_references
-\to \everysetupinteraction
+% \def\scrn_reference_enable_references
+% {\ifproductionrun
+% \clf_enableinteraction % only once anyway
+% \glet\scrn_reference_enable_references\relax
+% \fi}
+%
+% \appendtoks
+% \scrn_reference_enable_references
+% \to \everysetupinteraction
\setupinteraction % start fit page and reset form
[\c!openaction=,
diff --git a/tex/context/base/mkiv/scrn-wid.mkvi b/tex/context/base/mkiv/scrn-wid.mkvi
index c74125c72..d1571ca65 100644
--- a/tex/context/base/mkiv/scrn-wid.mkvi
+++ b/tex/context/base/mkiv/scrn-wid.mkvi
@@ -212,11 +212,10 @@
name {\attachmentparameter\c!name}%
buffer {\attachmentparameter\c!buffer}%
\relax
- \setbox\b_scrn_attachment_link\hbox{\scrn_attachment_place}%
\wd\b_scrn_attachment_link\currentattachmentwidth
\ht\b_scrn_attachment_link\currentattachmentheight
\dp\b_scrn_attachment_link\currentattachmentdepth
- \box\b_scrn_attachment_link}
+ \expandnamespaceparameter\??attachmentlocation\attachmentparameter\c!location\s!unknown}
\setvalue{\??attachmentmethod\v!hidden}%
{\clf_insertattachment
@@ -231,29 +230,48 @@
buffer {\attachmentparameter\c!buffer}%
\relax}
-\def\scrn_attachment_place
- {\executeifdefined
- {\??attachmentlocation\attachmentparameter\c!location}\hbox
- {\box\b_scrn_attachment_link}}
-
-\setvalue{\??attachmentlocation\v!inmargin }{\inmargin }
-\setvalue{\??attachmentlocation\v!leftedge }{\inleftedge }
-\setvalue{\??attachmentlocation\v!rightedge }{\inrightedge }
-\setvalue{\??attachmentlocation\v!leftmargin }{\inleftmargin }
-\setvalue{\??attachmentlocation\v!rightmargin}{\inrightmargin}
-\setvalue{\??attachmentlocation\v!high }{\high}
-\setvalue{\??attachmentlocation\v!none }{\scrn_attachment_collect}
-%setvalue{\??attachmentlocation\v!text }{\gobblenextargument} % gobbles the box
-
-\def\scrn_attachment_collect#content%
+\unexpanded\def\scrn_attachment_flush_traced
+ {\hpack\bgroup
+ \blackrule % can be a fast one
+ [ \c!color=trace:r,
+ \c!width=\wd\b_scrn_attachment_link,
+ \c!height=\ht\b_scrn_attachment_link,
+ \c!depth=\dp\b_scrn_attachment_link]%
+ \kern-\wd\b_scrn_attachment_link
+ \box\b_scrn_attachment_link
+ \egroup}
+
+\unexpanded\def\scrn_attachment_flush_normal
+ {\box\b_scrn_attachment_link}
+
+\installtextracker
+ {attachments.anchors}
+ {\let\scrn_attachment_flush\scrn_attachment_flush_traced}
+ {\let\scrn_attachment_flush\scrn_attachment_flush_normal}
+
+\let\scrn_attachment_flush\scrn_attachment_flush_normal
+
+\setvalue{\??attachmentlocation\v!inmargin }{\inmargin {\scrn_attachment_flush}}
+\setvalue{\??attachmentlocation\v!leftedge }{\inleftedge {\scrn_attachment_flush}}
+\setvalue{\??attachmentlocation\v!rightedge }{\inrightedge {\scrn_attachment_flush}}
+\setvalue{\??attachmentlocation\v!leftmargin }{\inleftmargin {\scrn_attachment_flush}}
+\setvalue{\??attachmentlocation\v!rightmargin}{\inrightmargin{\scrn_attachment_flush}}
+\setvalue{\??attachmentlocation\v!high }{\high {\scrn_attachment_flush}}
+
+\setvalue{\??attachmentlocation\v!none}%
{\global\setbox\b_scrn_attachment_collect\hbox\bgroup
\ifvoid\b_scrn_attachment_collect\else
\box\b_scrn_attachment_collect
\hskip\attachmentparameter\c!distance\relax
\fi
- #content%
+ \scrn_attachment_flush
\egroup}
+\setvalue{\??attachmentlocation\s!unknown}%
+ {\ifvoid\b_scrn_attachment_collect\else
+ \box\b_scrn_attachment_collect
+ \fi}
+
\unexpanded\def\placeattachments
{\ifvoid\b_scrn_attachment_collect\else
\box\b_scrn_attachment_collect
@@ -317,7 +335,7 @@
%
% test
%
-% \startcomment[symbol=Balloon]
+% \startcomment[symbol=Help]
% Do we want this kind of rubish?
% \stopcomment
%
@@ -360,6 +378,9 @@
%
% test
+%D The implementation is mostly the same as for attachments but sharing code
+%D will not make it cleaner.
+
\installcorenamespace{comment}
\installcorenamespace{commentlocation}
@@ -489,17 +510,37 @@
\dp\b_scrn_comment_link\currentcommentdepth
\expandnamespaceparameter\??commentlocation\commentparameter\c!location\s!unknown}
-\setvalue{\??commentmethods\v!hidden}%
- {}
+\letvalue{\??commentmethods\v!hidden}\donothing
+
+\unexpanded\def\scrn_comment_flush_traced
+ {\hpack\bgroup
+ \blackrule % can be a fast one
+ [ \c!color=trace:y,
+ \c!width=\wd\b_scrn_comment_link,
+ \c!height=\ht\b_scrn_comment_link,
+ \c!depth=\dp\b_scrn_comment_link]%
+ \kern-\wd\b_scrn_comment_link
+ \box\b_scrn_comment_link
+ \egroup}
+
+\unexpanded\def\scrn_comment_flush_normal
+ {\box\b_scrn_comment_link}
+
+\installtextracker
+ {comments.anchors}
+ {\let\scrn_comment_flush\scrn_comment_flush_traced}
+ {\let\scrn_comment_flush\scrn_comment_flush_normal}
+
+\let\scrn_comment_flush\scrn_comment_flush_normal
% todo: dedicated margin classes
-\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!inmargin }{\inmargin {\scrn_comment_flush}}
+\setvalue{\??commentlocation\v!leftedge }{\inleftedge {\scrn_comment_flush}}
+\setvalue{\??commentlocation\v!rightedge }{\inrightedge {\scrn_comment_flush}}
+\setvalue{\??commentlocation\v!leftmargin }{\inleftmargin {\scrn_comment_flush}}
+\setvalue{\??commentlocation\v!rightmargin}{\inrightmargin{\scrn_comment_flush}}
+\setvalue{\??commentlocation\v!high }{\high {\scrn_comment_flush}}
\setvalue{\??commentlocation\v!none}%
{\global\setbox\b_scrn_comment_collect\hbox\bgroup
@@ -507,7 +548,7 @@
\box\b_scrn_comment_collect
\hskip\commentparameter\c!distance\relax
\fi
- \box\b_scrn_comment_link
+ \scrn_comment_flush
\egroup}
\setvalue{\??commentlocation\s!unknown}%
diff --git a/tex/context/base/mkiv/scrp-cjk.lua b/tex/context/base/mkiv/scrp-cjk.lua
index b31dc335a..83eecf6a3 100644
--- a/tex/context/base/mkiv/scrp-cjk.lua
+++ b/tex/context/base/mkiv/scrp-cjk.lua
@@ -6,23 +6,24 @@ 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.
-
--- The input line endings: there is no way to distinguish between
--- inline spaces and endofline turned into spaces (would not make
--- sense either because otherwise a wanted space at the end of a
--- line would have to be a hard coded ones.
+-- We can speed this up by preallocating nodes and copying them but the gain is not
+-- that large.
+--
+-- If needed we can speed this up (traversers and prev next and such) but cjk
+-- documents don't have that many glyphs and certainly not much font processing so
+-- there not much gain in it.
+--
+-- The input line endings: there is no way to distinguish between inline spaces and
+-- endofline turned into spaces (would not make sense either because otherwise a
+-- wanted space at the end of a line would have to be a hard coded ones.
local nuts = nodes.nuts
-local tonut = nodes.tonut
-local tonode = nodes.tonode
local insert_node_after = nuts.insert_after
local insert_node_before = nuts.insert_before
local copy_node = nuts.copy
local remove_node = nuts.remove
-local traverse_id = nuts.traverse_id
+local nextglyph = nuts.traversers.glyph
local getnext = nuts.getnext
local getprev = nuts.getprev
@@ -41,12 +42,14 @@ local new_kern = nodepool.kern
local new_penalty = nodepool.penalty
local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
+local gluecodes = nodes.gluecodes
+
local glyph_code = nodecodes.glyph
local glue_code = nodecodes.glue
-local userskip_code = skipcodes.userskip
-local spaceskip_code = skipcodes.spaceskip
-local xspaceskip_code = skipcodes.xspaceskip
+
+local userskip_code = gluecodes.userskip
+local spaceskip_code = gluecodes.spaceskip
+local xspaceskip_code = gluecodes.xspaceskip
local a_scriptstatus = attributes.private('scriptstatus')
local a_scriptinjection = attributes.private('scriptinjection')
@@ -439,13 +442,16 @@ local injectors = { -- [previous] [current]
local function process(head,first,last)
if first ~= last then
- local lastfont, previous, last = nil, "start", nil
+ local lastfont = nil
+ local previous = "start"
+ local last = nil
while true do
- local upcoming, id = getnext(first), getid(first)
+ local upcoming = getnext(first)
+ local id = getid(first)
if id == glyph_code then
- local a = getattr(first,a_scriptstatus)
+ local a = getattr(first,a_scriptstatus)
local current = numbertocategory[a]
- local action = injectors[previous]
+ local action = injectors[previous]
if action then
action = action[current]
if action then
@@ -459,12 +465,16 @@ local function process(head,first,last)
end
previous = current
else -- glue
- local p, n = getprev(first), upcoming
+ local p = getprev(first)
+ local n = upcoming
if p and n then
- local pid, nid = getid(p), getid(n)
+ local pid = getid(p)
+ local nid = getid(n)
if pid == glyph_code and nid == glyph_code then
- local pa, na = getattr(p,a_scriptstatus), getattr(n,a_scriptstatus)
- local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na]
+ local pa = getattr(p,a_scriptstatus)
+ local na = getattr(n,a_scriptstatus)
+ local pcjk = pa and numbertocategory[pa]
+ local ncjk = na and numbertocategory[na]
if not pcjk or not ncjk
or pcjk == "korean" or ncjk == "korean"
or pcjk == "other" or ncjk == "other"
@@ -509,10 +519,9 @@ scripts.installmethod {
}
function scripts.decomposehangul(head)
- local head = tonut(head)
local done = false
- for current in traverse_id(glyph_code,head) do
- local lead_consonant, medial_vowel, tail_consonant = decomposed(getchar(current))
+ for current, char in nextglyph, head do
+ local lead_consonant, medial_vowel, tail_consonant = decomposed(char)
if lead_consonant then
setchar(current,lead_consonant)
local m = copy_node(current)
@@ -526,7 +535,7 @@ function scripts.decomposehangul(head)
done = true
end
end
- return tonode(head), done
+ return head, done
end
-- nodes.tasks.prependaction("processors","normalizers","scripts.decomposehangul")
@@ -695,13 +704,16 @@ local injectors = { -- [previous] [current]
local function process(head,first,last)
if first ~= last then
- local lastfont, previous, last = nil, "start", nil
+ local lastfont = nil
+ local previous = "start"
+ local last = nil
while true do
- local upcoming, id = getnext(first), getid(first)
+ local upcoming = getnext(first)
+ local id = getid(first)
if id == glyph_code then
- local a = getattr(first,a_scriptstatus)
+ local a = getattr(first,a_scriptstatus)
local current = numbertocategory[a]
- local action = injectors[previous]
+ local action = injectors[previous]
if action then
action = action[current]
if action then
@@ -715,12 +727,16 @@ local function process(head,first,last)
end
previous = current
else -- glue
- local p, n = getprev(first), upcoming
+ local p = getprev(first)
+ local n = upcoming
if p and n then
- local pid, nid = getid(p), getid(n)
+ local pid = getid(p)
+ local nid = getid(n)
if pid == glyph_code and nid == glyph_code then
- local pa, na = getattr(p,a_scriptstatus), getattr(n,a_scriptstatus)
- local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na]
+ local pa = getattr(p,a_scriptstatus)
+ local na = getattr(n,a_scriptstatus)
+ local pcjk = pa and numbertocategory[pa]
+ local ncjk = na and numbertocategory[na]
if not pcjk or not ncjk
or pcjk == "korean" or ncjk == "korean"
or pcjk == "other" or ncjk == "other"
@@ -917,13 +933,16 @@ local injectors = { -- [previous] [current]
local function process(head,first,last)
if first ~= last then
- local lastfont, previous, last = nil, "start", nil
+ local lastfont = nil
+ local previous = "start"
+ local last = nil
while true do
- local upcoming, id = getnext(first), getid(first)
+ local upcoming = getnext(first)
+ local id = getid(first)
if id == glyph_code then
- local a = getattr(first,a_scriptstatus)
+ local a = getattr(first,a_scriptstatus)
local current = numbertocategory[a]
- local action = injectors[previous]
+ local action = injectors[previous]
if action then
action = action[current]
if action then
@@ -940,12 +959,16 @@ local function process(head,first,last)
-- upcoming = getnext(end_of_math(current))
-- previous = "start"
else -- glue
- local p, n = getprev(first), upcoming -- we should remember prev
+ local p = getprev(first)
+ local n = upcoming
if p and n then
- local pid, nid = getid(p), getid(n)
+ local pid = getid(p)
+ local nid = getid(n)
if pid == glyph_code and nid == glyph_code then
- local pa, na = getattr(p,a_scriptstatus), getattr(n,a_scriptstatus)
- local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na]
+ local pa = getattr(p,a_scriptstatus)
+ local na = getattr(n,a_scriptstatus)
+ local pcjk = pa and numbertocategory[pa]
+ local ncjk = na and numbertocategory[na]
if not pcjk or not ncjk
or pcjk == "korean" or ncjk == "korean"
or pcjk == "other" or ncjk == "other"
diff --git a/tex/context/base/mkiv/scrp-eth.lua b/tex/context/base/mkiv/scrp-eth.lua
index 43cb2ff6a..f6a994b88 100644
--- a/tex/context/base/mkiv/scrp-eth.lua
+++ b/tex/context/base/mkiv/scrp-eth.lua
@@ -12,71 +12,16 @@ if not modules then modules = { } end modules ['scrp-eth'] = {
local nuts = nodes.nuts
local getnext = nuts.getnext
-local getfont = nuts.getfont
-local getid = nuts.getid
+local ischar = nuts.ischar
local getattr = nuts.getattr
-local insert_node_before = nuts.insert_before
-
-local nodepool = nuts.pool
-
-local new_glue = nodepool.glue
-local new_penalty = nodepool.penalty
-
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
local a_scriptstatus = attributes.private('scriptstatus')
-local a_scriptinjection = attributes.private('scriptinjection')
-local categorytonumber = scripts.categorytonumber
local numbertocategory = scripts.numbertocategory
-local hash = scripts.hash
-local numbertodataset = scripts.numbertodataset
-
-local fonthashes = fonts.hashes
-local parameters = fonthashes.parameters
-
-local space, stretch, shrink, lastfont
-
-local inter_character_space_factor = 1
-local inter_character_stretch_factor = 1
-local inter_character_shrink_factor = 1
-
-local function space_glue(current)
- local data = numbertodataset[getattr(current,a_scriptinjection)]
- if data then
- inter_character_space_factor = data.inter_character_space_factor or 1
- inter_character_stretch_factor = data.inter_character_stretch_factor or 1
- inter_character_shrink_factor = data.inter_character_shrink_factor or 1
- end
- local font = getfont(current)
- if lastfont ~= font then
- local pf = parameters[font]
- space = pf.space
- stretch = pf.space_stretch
- shrink = pf.space_shrink
- lastfont = font
- end
- return new_glue(
- inter_character_space_factor * space,
- inter_character_stretch_factor * stretch,
- inter_character_shrink_factor * shrink
- )
-end
-
-local function insert_space(head,current)
- insert_node_before(head,current,space_glue(current))
-end
-
-local function insert_zerowidthspace(head,current)
- insert_node_before(head,current,new_glue(0))
-end
-
-local function insert_nobreakspace(head,current)
- insert_node_before(head,current,new_penalty(10000))
- insert_node_before(head,current,space_glue(current))
-end
+local inserters = scripts.inserters
-- syllable [zerowidthspace] syllable
-- syllable [zerowidthspace] word
@@ -88,21 +33,22 @@ end
-- sentence [space] word
-- sentence [space] sentence
+
local injectors = { -- [previous] [current]
ethiopic_syllable = {
- ethiopic_syllable = insert_zerowidthspace,
- ethiopic_word = insert_nobreakspace,
- ethiopic_sentence = insert_nobreakspace,
+ ethiopic_syllable = inserters.zerowidthspace_before,
+ ethiopic_word = inserters.nobreakspace_before,
+ ethiopic_sentence = inserters.nobreakspace_before,
},
ethiopic_word = {
- ethiopic_syllable = insert_space,
- ethiopic_word = insert_space,
- ethiopic_sentence = insert_space,
+ ethiopic_syllable = inserters.space_before,
+ ethiopic_word = inserters.space_before,
+ ethiopic_sentence = inserters.space_before,
},
ethiopic_sentence = {
- ethiopic_syllable = insert_space,
- ethiopic_word = insert_space,
- ethiopic_sentence = insert_space,
+ ethiopic_syllable = inserters.space_before,
+ ethiopic_word = inserters.space_before,
+ ethiopic_sentence = inserters.space_before,
},
}
@@ -111,10 +57,10 @@ local function process(head,first,last)
local injector = false
local current = first
while current do
- local id = getid(current)
- if id == glyph_code then
+ local char, id = ischar(current)
+ if char then
local scriptstatus = getattr(current,a_scriptstatus)
- local category = numbertocategory[scriptstatus]
+ local category = numbertocategory[scriptstatus]
if injector then
local action = injector[category]
if action then
@@ -122,8 +68,6 @@ local function process(head,first,last)
end
end
injector = injectors[category]
- else
- -- nothing yet
end
if current == last then
break
diff --git a/tex/context/base/mkiv/scrp-ini.lua b/tex/context/base/mkiv/scrp-ini.lua
index 9bd70e30a..e6aa5f072 100644
--- a/tex/context/base/mkiv/scrp-ini.lua
+++ b/tex/context/base/mkiv/scrp-ini.lua
@@ -22,72 +22,75 @@ local report_splitting = logs.reporter("scripts","splitting")
local utfbyte, utfsplit = utf.byte, utf.split
local gmatch = string.gmatch
-local attributes = attributes
-local nodes = nodes
-local context = context
+local attributes = attributes
+local nodes = nodes
+local context = context
-local texsetattribute = tex.setattribute
+local texsetattribute = tex.setattribute
-local nodecodes = nodes.nodecodes
-local unsetvalue = attributes.unsetvalue
+local nodecodes = nodes.nodecodes
+local unsetvalue = attributes.unsetvalue
-local implement = interfaces.implement
+local implement = interfaces.implement
-local glyph_code = nodecodes.glyph
-local glue_code = nodecodes.glue
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
-local emwidths = fonts.hashes.emwidths
-local exheights = fonts.hashes.exheights
+local emwidths = fonts.hashes.emwidths
+local exheights = fonts.hashes.exheights
-local a_scriptinjection = attributes.private('scriptinjection')
-local a_scriptsplitting = attributes.private('scriptsplitting')
-local a_scriptstatus = attributes.private('scriptstatus')
+local a_scriptinjection = attributes.private('scriptinjection')
+local a_scriptsplitting = attributes.private('scriptsplitting')
+local a_scriptstatus = attributes.private('scriptstatus')
-local fontdata = fonts.hashes.identifiers
-local allocate = utilities.storage.allocate
-local setnodecolor = nodes.tracers.colors.set
-local setmetatableindex = table.setmetatableindex
+local fontdata = fonts.hashes.identifiers
+local allocate = utilities.storage.allocate
+local setnodecolor = nodes.tracers.colors.set
+local setmetatableindex = table.setmetatableindex
-local enableaction = nodes.tasks.enableaction
-local disableaction = nodes.tasks.disableaction
+local enableaction = nodes.tasks.enableaction
+local disableaction = nodes.tasks.disableaction
-local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
+local nuts = nodes.nuts
-local getnext = nuts.getnext
-local getchar = nuts.getchar
-local getfont = nuts.getfont
-local getid = nuts.getid
-local getattr = nuts.getattr
-local setattr = nuts.setattr
-local isglyph = nuts.isglyph
+local getnext = nuts.getnext
+local getchar = nuts.getchar
+local getfont = nuts.getfont
+local getid = nuts.getid
+local getattr = nuts.getattr
+local setattr = nuts.setattr
+local isglyph = nuts.isglyph
-local insert_node_after = nuts.insert_after
-local first_glyph = nuts.first_glyph
-local traverse_id = nuts.traverse_id
-local traverse_char = nuts.traverse_char
+local insert_node_after = nuts.insert_after
+local insert_node_before = nuts.insert_before
-local nodepool = nuts.pool
+local first_glyph = nuts.first_glyph
-local new_glue = nodepool.glue
-local new_rule = nodepool.rule
-local new_penalty = nodepool.penalty
+----- traverse_id = nuts.traverse_id
+----- traverse_char = nuts.traverse_char
+local nextglyph = nuts.traversers.glyph
+local nextchar = nuts.traversers.char
-scripts = scripts or { }
-local scripts = scripts
+local nodepool = nuts.pool
-scripts.hash = scripts.hash or { }
-local hash = scripts.hash
+local new_glue = nodepool.glue
+local new_rule = nodepool.rule
+local new_penalty = nodepool.penalty
-local handlers = allocate()
-scripts.handlers = handlers
+scripts = scripts or { }
+local scripts = scripts
-local injectors = allocate()
-scripts.injectors = handlers
+scripts.hash = scripts.hash or { }
+local hash = scripts.hash
-local splitters = allocate()
-scripts.splitters = splitters
+local handlers = allocate()
+scripts.handlers = handlers
+
+local injectors = allocate()
+scripts.injectors = handlers
+
+local splitters = allocate()
+scripts.splitters = splitters
local hash = { -- we could put these presets in char-def.lua
--
@@ -206,6 +209,11 @@ local hash = { -- we could put these presets in char-def.lua
[0x1361] = "ethiopic_word",
[0x1362] = "ethiopic_sentence",
--
+ -- tibetan:
+ --
+ [0x0F0B] = "breaking_tsheg",
+ [0x0F0C] = "nonbreaking_tsheg",
+
}
local function provide(t,k)
@@ -225,6 +233,7 @@ local function provide(t,k)
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"
+ elseif (k >= 0x00F00 and k <= 0x00FFF) then v = "tibetan"
else v = false
end
t[k] = v
@@ -267,6 +276,7 @@ function scripts.installmethod(handler)
report_preprocessing("missing (default) dataset in script %a",name)
datasets.default = { } -- slower but an error anyway
end
+
for k, v in next, datasets do
setmetatableindex(v,defaults)
end
@@ -387,6 +397,8 @@ local scriptcolors = allocate { -- todo: just named colors
ethiopic_syllable = "trace:1",
ethiopic_word = "trace:2",
ethiopic_sentence = "trace:3",
+ breaking_tsheg = "trace:1",
+ nonbreaking_tsheg = "trace:2",
}
scripts.colors = scriptcolors
@@ -409,6 +421,8 @@ local numbertocategory = allocate { -- rather bound to cjk ... will be generaliz
"ethiopic_syllable",
"ethiopic_word",
"ethiopic_sentence",
+ "breaking_tsheg",
+ "nonbreaking_tsheg",
}
local categorytonumber = allocate(table.swapped(numbertocategory)) -- could be one table
@@ -417,7 +431,7 @@ scripts.categorytonumber = categorytonumber
scripts.numbertocategory = numbertocategory
local function colorize(start,stop)
- for n in traverse_id(glyph_code,start) do
+ for n in nextglyph, start do
local kind = numbertocategory[getattr(n,a_scriptstatus)]
if kind then
local ac = scriptcolors[kind]
@@ -450,13 +464,12 @@ end
-- we can have a fonts.hashes.originals
function scripts.injectors.handler(head)
- head = tonut(head)
local start = first_glyph(head) -- we already have glyphs here (subtype 1)
if not start then
- return tonode(head), false
+ return head
else
- local last_a, normal_process, lastfont, originals = nil, nil, nil, nil
- local done, first, last, ok = false, nil, nil, false
+ local last_a, normal_process, lastfont, originals, first, last
+ local ok = false
while start do
local char, id = isglyph(start)
if char then
@@ -473,7 +486,7 @@ function scripts.injectors.handler(head)
else
normal_process(head,first,last)
end
- ok, done = false, true
+ ok = false
end
first, last = nil, nil
end
@@ -482,16 +495,15 @@ function scripts.injectors.handler(head)
normal_process = handler.injector
end
if normal_process then
- -- wrong: originals are indices !
- local font = getfont(start)
- if font ~= lastfont then
- originals = fontdata[font].resources
+ -- id == font
+ if id ~= lastfont then
+ originals = fontdata[id].resources
if resources then
originals = resources.originals
else
originals = nil -- can't happen
end
- lastfont = font
+ lastfont = id
end
if originals and type(originals) == "number" then
char = originals[char] or char
@@ -517,7 +529,7 @@ function scripts.injectors.handler(head)
else
normal_process(head,first,last)
end
- ok, done = false, true
+ ok = false
end
first, last = nil, nil
end
@@ -532,7 +544,7 @@ function scripts.injectors.handler(head)
else
normal_process(head,first,last)
end
- ok, done = false, true
+ ok = false
end
first, last = nil, nil
end
@@ -554,7 +566,7 @@ function scripts.injectors.handler(head)
else
normal_process(head,first,last)
end
- first, last, ok, done = nil, nil, false, true
+ first, last, ok = nil, nil, false
elseif first then
first, last = nil, nil
end
@@ -570,16 +582,15 @@ function scripts.injectors.handler(head)
else
normal_process(head,first,last)
end
- done = true
end
- return tonode(head), done
+ return head
end
end
-- kind of experimental .. might move to it's own module
-- function scripts.splitters.handler(head)
--- return head, false
+-- return head
-- end
local function addwords(tree,data)
@@ -701,32 +712,6 @@ end)
local categories = characters.categories or { }
--- local function hit(root,head)
--- local current = getnext(head)
--- local lastrun = false
--- local lastfinal = false
--- while current and getid(current) == glyph_code do
--- local char = getchar(current)
--- local newroot = root[char]
--- if newroot then
--- local final = newroot.final
--- if final then
--- lastrun = current
--- lastfinal = final
--- end
--- root = newroot
--- elseif categories[char] == "mn" then
--- -- continue
--- else
--- return lastrun, lastfinal
--- end
--- current = getnext(current)
--- end
--- if lastrun then
--- return lastrun, lastfinal
--- end
--- end
-
local function hit(root,head)
local current = getnext(head)
local lastrun = false
@@ -759,9 +744,7 @@ end
local tree, attr, proc
function splitters.handler(head) -- todo: also first_glyph test
- head = tonut(head)
local current = head
- local done = false
while current do
if getid(current) == glyph_code then
local a = getattr(current,a_scriptsplitting)
@@ -792,7 +775,6 @@ function splitters.handler(head) -- todo: also first_glyph test
end
end
head, current = proc(handler,head,current,last,1)
- done = true
else
if trace_splitdetail then
-- could be punctuation
@@ -803,7 +785,6 @@ function splitters.handler(head) -- todo: also first_glyph test
end
end
head, current = proc(handler,head,current,last,2)
- done = true
end
end
end
@@ -813,7 +794,7 @@ function splitters.handler(head) -- todo: also first_glyph test
end
current = getnext(current)
end
- return tonode(head), done
+ return head
end
local function marker(head,current,font,color) -- could become: nodes.tracers.marker
@@ -907,15 +888,13 @@ setmetatableindex(cache_nop,function(t,k) local v = { } t[k] = v return v end)
-- playing nice
function autofontfeature.handler(head)
- for n in traverse_char(tonut(head)) do
+ for n, char, font in nextchar, head do
-- if getattr(n,a_scriptinjection) then
-- -- already tagged by script feature, maybe some day adapt
-- else
- local char = getchar(n)
local script = otfscripts[char]
if script then
local dynamic = getattr(n,0) or 0
- local font = getfont(n)
if dynamic > 0 then
local slot = cache_yes[font]
local attr = slot[script]
@@ -980,3 +959,73 @@ implement {
name = "resetscript",
actions = scripts.reset
}
+
+-- some common helpers
+
+
+do
+
+ local parameters = fonts.hashes.parameters
+
+ local space, stretch, shrink, lastfont
+
+ local inter_character_space_factor = 1
+ local inter_character_stretch_factor = 1
+ local inter_character_shrink_factor = 1
+
+ local function space_glue(current)
+ local data = numbertodataset[getattr(current,a_scriptinjection)]
+ if data then
+ inter_character_space_factor = data.inter_character_space_factor or 1
+ inter_character_stretch_factor = data.inter_character_stretch_factor or 1
+ inter_character_shrink_factor = data.inter_character_shrink_factor or 1
+ end
+ local font = getfont(current)
+ if lastfont ~= font then
+ local pf = parameters[font]
+ space = pf.space
+ stretch = pf.space_stretch
+ shrink = pf.space_shrink
+ lastfont = font
+ end
+ return new_glue(
+ inter_character_space_factor * space,
+ inter_character_stretch_factor * stretch,
+ inter_character_shrink_factor * shrink
+ )
+ end
+
+ scripts.inserters = {
+
+ space_before = function(head,current)
+ return insert_node_before(head,current,space_glue(current))
+ end,
+ space_after = function(head,current)
+ return insert_node_after(head,current,space_glue(current))
+ end,
+
+ zerowidthspace_before = function(head,current)
+ return insert_node_before(head,current,new_glue(0))
+ end,
+ zerowidthspace_after = function(head,current)
+ return insert_node_after(head,current,new_glue(0))
+ end,
+
+ nobreakspace_before = function(head,current)
+ local g = space_glue(current)
+ local p = new_penalty(10000)
+ head, current = insert_node_before(head,current,p)
+ return insert_node_before(head,current,g)
+ end,
+ nobreakspace_after = function(head,current)
+ local g = space_glue(current)
+ local p = new_penalty(10000)
+ head, current = insert_node_after(head,current,g)
+ return insert_node_after(head,current,p)
+ end,
+
+ }
+
+end
+
+-- end of helpers
diff --git a/tex/context/base/mkiv/scrp-ini.mkiv b/tex/context/base/mkiv/scrp-ini.mkiv
index 8f28f505d..f2d1da627 100644
--- a/tex/context/base/mkiv/scrp-ini.mkiv
+++ b/tex/context/base/mkiv/scrp-ini.mkiv
@@ -17,10 +17,11 @@
\registerctxluafile{scrp-cjk}{}
\registerctxluafile{scrp-eth}{}
\registerctxluafile{scrp-tha}{}
+\registerctxluafile{scrp-tib}{}
-\definesystemattribute[scriptinjection][public]
-\definesystemattribute[scriptsplitting][public]
-\definesystemattribute[scriptstatus] [public]
+\definesystemattribute[scriptinjection][public,pickup]
+\definesystemattribute[scriptsplitting][public,pickup]
+\definesystemattribute[scriptstatus] [public,pickup]
%D Since scripts need specific \LUA\ code we use hard coded attribute
%D values, but we might have more tricks at some time, so we use a
@@ -43,10 +44,23 @@
\unexpanded\def\scripts_basics_set
{\clf_setscript{\currentscript}{\scriptparameter\c!method}{\scriptparameter\c!preset}}
-\unexpanded\def\setscript[#1]%
+% \unexpanded\def\setscript[#1]%
+% {\edef\currentscript{#1}%
+% \scripts_basics_set}
+
+\unexpanded\def\setglobalscript[#1]%
+ {\edef\currentscript{#1}%
+ \scripts_basics_set
+ \pickupscriptinjectionattribute
+ \pickupscriptsplittingattribute
+ \pickupscriptstatusattribute}
+
+\unexpanded\def\setlocalscript[#1]%
{\edef\currentscript{#1}%
\scripts_basics_set}
+\let\setscript\setlocalscript
+
\unexpanded\def\resetscript
{\clf_resetscript}
@@ -73,6 +87,7 @@
\definescript [nihongo] [\c!method=nihongo]
\definescript [ethiopic] [\c!method=ethiopic]
\definescript [thai] [\c!method=thai]
+\definescript [tibetan] [\c!method=tibetan]
\definescript [latin] [\c!method=] % resets the attribute (also currentscript)
diff --git a/tex/context/base/mkiv/scrp-tib.lua b/tex/context/base/mkiv/scrp-tib.lua
new file mode 100644
index 000000000..b67f69648
--- /dev/null
+++ b/tex/context/base/mkiv/scrp-tib.lua
@@ -0,0 +1,81 @@
+if not modules then modules = { } end modules ['scrp-tib'] = {
+ version = 1.001,
+ comment = "companion to scrp-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local nuts = nodes.nuts
+
+local getnext = nuts.getnext
+local getattr = nuts.getattr
+local ischar = nuts.ischar
+
+local a_scriptstatus = attributes.private('scriptstatus')
+
+local numbertocategory = scripts.numbertocategory
+local inserters = scripts.inserters
+
+local injectors = {
+ breaking_tsheg = inserters.space_after,
+}
+
+-- more efficient is to check directly
+--
+-- local b_tsheg = 0x0F0B -- breaking
+-- local n_tsheg = 0x0F0C -- nonbreaking
+--
+-- if char == b_tsheg then
+-- head, current = insert_space_after(head,current)
+-- end
+--
+-- but this is more general
+
+local function process(head,first,last)
+ if first ~= last then
+ local current = first
+ while current do
+ local char, id = ischar(current)
+ if char then
+ local scriptstatus = getattr(current,a_scriptstatus)
+ if scriptstatus and scriptstatus > 0 then
+ local category = numbertocategory[scriptstatus]
+ if category then
+ local injector = injectors[category]
+ if injector then
+ head, current = injector(head,current)
+ end
+ end
+ end
+ end
+ if current == last then
+ break
+ else
+ current = getnext(current)
+ end
+ end
+ end
+end
+
+scripts.installmethod {
+ name = "tibetan",
+ injector = process,
+ datasets = {
+ default = {
+ inter_character_space_factor = 1,
+ inter_character_stretch_factor = 1,
+ inter_character_shrink_factor = 1,
+ },
+ half = {
+ inter_character_space_factor = 0.5,
+ inter_character_stretch_factor = 0.5,
+ inter_character_shrink_factor = 0.5,
+ },
+ quarter = {
+ inter_character_space_factor = 0.25,
+ inter_character_stretch_factor = 0.25,
+ inter_character_shrink_factor = 0.25,
+ },
+ },
+}
diff --git a/tex/context/base/mkiv/sort-ini.lua b/tex/context/base/mkiv/sort-ini.lua
index f90b70be5..0916337b1 100644
--- a/tex/context/base/mkiv/sort-ini.lua
+++ b/tex/context/base/mkiv/sort-ini.lua
@@ -401,8 +401,10 @@ local function basic(a,b) -- trace ea and eb
-- hashed (shared) entries
return 0
end
- local ea, eb = a.split, b.split
- local na, nb = #ea, #eb
+ local ea = a.split
+ local eb = b.split
+ local na = #ea
+ local nb = #eb
if na == 0 and nb == 0 then
-- simple variant (single word)
local result = 0
@@ -414,7 +416,8 @@ local function basic(a,b) -- trace ea and eb
end
end
if result == 0 then
- local la, lb = #ea.uc, #eb.uc
+ local la = #ea.uc
+ local lb = #eb.uc
if la > lb then
return 1
elseif lb > la then
@@ -429,7 +432,8 @@ local function basic(a,b) -- trace ea and eb
-- complex variant, used in register (multiple words)
local result = 0
for i=1,nb < na and nb or na do
- local eai, ebi = ea[i], eb[i]
+ local eai = ea[i]
+ local ebi = eb[i]
for j=1,#sequence do
local m = sequence[j]
result = basicsort(eai[m],ebi[m])
@@ -438,7 +442,8 @@ local function basic(a,b) -- trace ea and eb
end
end
if result == 0 then
- local la, lb = #eai.uc, #ebi.uc
+ local la = #eai.uc
+ local lb = #ebi.uc
if la > lb then
return 1
elseif lb > la then
@@ -586,8 +591,18 @@ function splitters.utf(str,checked) -- we could append m and u but this is clean
-- end
-- end
end
- local m_case, z_case, p_case, m_mapping, z_mapping, p_mapping, char, byte, n = { }, { }, { }, { }, { }, { }, { }, { }, 0
- local nm, nz, np = 0, 0, 0
+ local m_case = { }
+ local z_case = { }
+ local p_case = { }
+ local m_mapping = { }
+ local z_mapping = { }
+ local p_mapping = { }
+ local char = { }
+ local byte = { }
+ local n = 0
+ local nm = 0
+ local nz = 0
+ local np = 0
for sc in utfcharacters(str) do
local b = utfbyte(sc)
if b >= digitsoffset then
diff --git a/tex/context/base/mkiv/sort-lan.lua b/tex/context/base/mkiv/sort-lan.lua
index 1aa173d1b..b27798966 100644
--- a/tex/context/base/mkiv/sort-lan.lua
+++ b/tex/context/base/mkiv/sort-lan.lua
@@ -71,16 +71,22 @@ definitions['fr'] = { parent = 'default' }
-- DIN 5007-1
-definitions['DIN 5007-1'] = { parent = 'default' }
+definitions['DIN 5007-1'] = {
+ parent = 'default',
+ replacements = {
+ { "ß", "ss" },
+ },
+}
-- DIN 5007-2
definitions['DIN 5007-2'] = {
parent = 'default',
replacements = {
- { "ä", 'ae' }, { "Ä", 'Ae' },
- { "ö", 'oe' }, { "Ö", 'Oe' },
- { "ü", 'ue' }, { "Ü", 'Ue' },
+ { "ä", "ae" }, { "Ä", "Ae" },
+ { "ö", "oe" }, { "Ö", "Oe" },
+ { "ü", "ue" }, { "Ü", "Ue" },
+ { "ß", "ss" },
},
}
@@ -88,7 +94,9 @@ definitions['DIN 5007-2'] = {
definitions['Duden'] = {
parent = 'default',
- replacements = { { "ß", 's' } },
+ replacements = {
+ { "ß", "s" },
+ },
}
-- definitions['de'] = { parent = 'default' } -- new german
@@ -126,7 +134,7 @@ definitions['de-AT'] = {
},
}
--- finish (by Wolfgang Schuster)
+-- finnish (by Wolfgang Schuster)
definitions['fi'] = {
entries = {
@@ -897,22 +905,24 @@ definitions["hu"] = {
},
}
---- Estonian
+-- Estonian
definitions["et"] = {
- entries = { -- w x y are used for foreign words only
- ["a"] = "a", ["b"] = "b", ["d"] = "d", ["e"] = "e", ["f"] = "f",
- ["g"] = "g", ["h"] = "h", ["i"] = "i", ["j"] = "j", ["k"] = "k",
- ["l"] = "l", ["m"] = "m", ["n"] = "n", ["o"] = "o", ["p"] = "p",
- ["r"] = "r", ["s"] = "s", ["š"] = "š", ["z"] = "z", ["ž"] = "ž",
- ["t"] = "t", ["u"] = "u", ["v"] = "v", ["w"] = "v", ["õ"] = "õ",
- ["ä"] = "ä", ["ö"] = "ö", ["ü"] = "ü", ["x"] = "x", ["y"] = "y",
+ entries = { -- f š z ž are used in estonian words of foreign origin, c č q w x y are used for foreign words only
+ ["a"] = "a", ["b"] = "b", ["c"] = "c", ["č"] = "č", ["d"] = "d",
+ ["e"] = "e", ["f"] = "f", ["g"] = "g", ["h"] = "h", ["i"] = "i",
+ ["j"] = "j", ["k"] = "k", ["l"] = "l", ["m"] = "m", ["n"] = "n",
+ ["o"] = "o", ["p"] = "p", ["q"] = "q", ["r"] = "r", ["s"] = "s",
+ ["š"] = "š", ["z"] = "z", ["ž"] = "ž", ["t"] = "t", ["u"] = "u",
+ ["v"] = "v", ["w"] = "w", ["õ"] = "õ", ["ä"] = "ä", ["ö"] = "ö",
+ ["ü"] = "ü", ["x"] = "x", ["y"] = "y",
},
orders = {
- "a", "b", "d", "e", "f", "g", "h", "i", "j", "k",
- "l", "m", "n", "o", "p", "r", "s", "š", "z", "ž",
- "t", "u", "v", "w", "õ", "ä", "ö", "ü", "x", "y",
- }
+ "a", "b", "c", "č", "d", "e", "f", "g", "h", "i",
+ "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
+ "š", "z", "ž", "t", "u", "v", "w", "õ", "ä", "ö",
+ "ü", "x", "y",
+ },
}
--- Korean
diff --git a/tex/context/base/mkiv/spac-adj.lua b/tex/context/base/mkiv/spac-adj.lua
deleted file mode 100644
index 3db59881b..000000000
--- a/tex/context/base/mkiv/spac-adj.lua
+++ /dev/null
@@ -1,67 +0,0 @@
-if not modules then modules = { } end modules ['spac-adj'] = {
- version = 1.001,
- comment = "companion to spac-adj.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- sort of obsolete code
-
-local a_vadjust = attributes.private('graphicvadjust')
-
-local nodecodes = nodes.nodecodes
-
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-
-local remove_node = nodes.remove
-local hpack_node = node.hpack
-
-local enableaction = nodes.tasks.enableaction
-
-function nodes.handlers.graphicvadjust(head,groupcode) -- we can make an actionchain for mvl only
- if groupcode == "" then -- mvl only
- local h, p, done = head, nil, false
- while h do
- local id = h.id
- if id == hlist_code or id == vlist_code then
- local a = h[a_vadjust]
- if a then
- if p then
- local n
- head, h, n = remove_node(head,h)
- local pl = p.list
- if n.width ~= 0 then
- n = hpack_node(n,0,'exactly') -- todo: dir
- end
- if pl then
- pl.prev = n
- n.next = pl
- end
- p.list = n
- done = true
- else
- -- can't happen
- end
- else
- p = h
- h = h.next
- end
- else
- h = h.next
- end
- end
- return head, done
- else
- return head, false
- end
-end
-
-interfaces.implement {
- name = "enablegraphicvadjust",
- onlyonce = true,
- actions = function()
- enableaction("finalizers","nodes.handlers.graphicvadjust")
- end
-}
diff --git a/tex/context/base/mkiv/spac-adj.mkiv b/tex/context/base/mkiv/spac-adj.mkiv
deleted file mode 100644
index d29d15c17..000000000
--- a/tex/context/base/mkiv/spac-adj.mkiv
+++ /dev/null
@@ -1,51 +0,0 @@
-%D \module
-%D [ file=spac-adj, % moved from spac-par.mkiv
-%D version=2009.10.16, % 1997.03.31, was core-spa.tex
-%D title=\CONTEXT\ Spacing Macros,
-%D subtitle=Paragraphs,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-\writestatus{loading}{ConTeXt Spacing Macros / Adjustments}
-
-\unprotect
-
-% Very nasty but needed for margin stuff inside colored
-% paragraphs. Obsolete for while .
-
-\registerctxluafile{spac-adj}{}
-
-\definesystemattribute [graphicvadjust] [public]
-
-\unexpanded\def\enablegraphicvadjust
- {\writestatus\m!system{graphicvadjusting is no longer needed!}
- \clf_enablegraphicvadjust %once anyway
- \glet\enablegraphicvadjust\relax}
-
-\unexpanded\def\graphicvadjust % currently not enabled ... nasty bidi handling
- {\clf_enablegraphicvadjust % and probably no longer needed anyway
- \dowithnextboxcontentcs\forgetall\spac_vadjust_graphic_finish\vbox}
-
-\def\spac_vadjust_graphic_finish
- {\vadjust
- {\vbox attr \graphicvadjustattribute \plusone
- {\unvbox\nextbox
- % corrects for one line paragraphs
- \nointerlineskip
- \kern-\struttotal
- \nointerlineskip
- \verticalstrut}}}
-
-\unexpanded\def\fakedvadjust
- {\dowithnextboxcs\spac_vadjust_faked_finish\vtop}
-
-\def\spac_vadjust_faked_finish
- {\setbox\nextbox\hpack{\llap{\lower\strutdepth\box\nextbox}}%
- \smashedbox\nextbox}
-
-\protect \endinput
diff --git a/tex/context/base/mkiv/spac-ali.lua b/tex/context/base/mkiv/spac-ali.lua
index 640478d34..b58040ac7 100644
--- a/tex/context/base/mkiv/spac-ali.lua
+++ b/tex/context/base/mkiv/spac-ali.lua
@@ -38,7 +38,8 @@ local listcodes = nodes.listcodes
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
-local line_code = listcodes.line
+
+local linelist_code = listcodes.line
local new_stretch = nodepool.stretch
@@ -63,13 +64,12 @@ local nofrealigned = 0
-- raggedright 0 0 fil
-- raggedcenter 0 + 0 + -
-local function handler(head,leftpage,realpageno)
+local function handler(head,leftpage,realpageno) -- traverse_list
local current = head
- local done = false
while current do
local id = getid(current)
if id == hlist_code then
- if getsubtype(current) == line_code then
+ if getsubtype(current) == linelist_code then
local a = takeattr(current,a_realign)
if not a or a == 0 then
-- skip
@@ -102,7 +102,6 @@ local function handler(head,leftpage,realpageno)
elseif trace_realign then
report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno)
end
- done = true
nofrealigned = nofrealigned + 1
end
end
@@ -113,14 +112,11 @@ local function handler(head,leftpage,realpageno)
end
current = getnext(current)
end
- return head, done
+ return head
end
function alignments.handler(head)
- local leftpage = isleftpage()
- local realpageno = texgetcount("realpageno")
- local head, done = handler(tonut(head),leftpage,realpageno)
- return tonode(head), done
+ return handler(head,isleftpage(),texgetcount("realpageno"))
end
local enabled = false
diff --git a/tex/context/base/mkiv/spac-ali.mkiv b/tex/context/base/mkiv/spac-ali.mkiv
index fbcf45caa..4362ff250 100644
--- a/tex/context/base/mkiv/spac-ali.mkiv
+++ b/tex/context/base/mkiv/spac-ali.mkiv
@@ -27,7 +27,7 @@
%
% but that also means myoption gets frozen due to caching.
-\registerctxluafile{spac-ali}{}
+\registerctxluafile{spac-ali}{optimize}
\definesystemattribute[realign] [public] % might be combined with the next one
\definesystemattribute[alignstate][public] % will make a single attributes for several states
@@ -61,16 +61,6 @@
\newtoks\everyresetalign % todo
-%D We will not use bodydir and pagedir so we disable them. That way we get
-%D normal hyperlink support. We back on it (too hard to fake \type {\the}).
-
-\unexpanded\def\syst_fatal_dir_error#1%
- {\writestatus{fatal error}{\string#1\space is forbidden}%
- \wait}
-
-\def\pagedir {\syst_fatal_dir_error\pagedir} \let\normalpagedir\pagedir
-\def\bodydir {\syst_fatal_dir_error\bodydir} \let\normalbodydir\bodydir
-
% This will become a more advanced layout controller soon:
\newconditional\layoutlefttoright \settrue\layoutlefttoright
@@ -94,63 +84,23 @@
\unexpanded\def\spac_directions_lefttoright_vmode
{\settrue\displaylefttoright
\settrue\inlinelefttoright
- \textdir TLT\relax
- \pardir TLT\relax}
+ \textdirection\directionlefttoright
+ \pardirection \directionlefttoright}
\unexpanded\def\spac_directions_righttoleft_vmode
{\setfalse\displaylefttoright
\setfalse\inlinelefttoright
- \textdir TRT\relax
- \pardir TRT\relax}
-
-% % keep this as reference
-%
-% \unexpanded\def\spac_directions_lefttoright_hmode
-% {\textdir TLT\relax
-% \settrue\inlinelefttoright}
-%
-% \unexpanded\def\spac_directions_righttoleft_hmode
-% {\textdir TRT\relax
-% \setfalse\inlinelefttoright}
-%
-% \unexpanded\def\spac_directions_lefttoright_hmode
-% {\ifzeropt\lastskip
-% \textdir TLT\relax
-% \else
-% \scratchskip\lastskip
-% \unskip
-% \textdir TLT\relax
-% \hskip\scratchskip
-% \fi
-% \settrue\inlinelefttoright}
-%
-% \unexpanded\def\spac_directions_righttoleft_hmode
-% {\ifzeropt\lastskip
-% \textdir TRT\relax
-% \else
-% \scratchskip\lastskip
-% \unskip
-% \textdir TRT\relax
-% \hskip\scratchskip
-% \fi
-% \setfalse\inlinelefttoright}
+ \textdirection\directionrighttoleft
+ \pardirection \directionrighttoleft}
\unexpanded\def\spac_directions_lefttoright_hmode
- {\linedir TLT\relax % linedir keeps subtype of skip
+ {\linedirection\directionlefttoright % linedir keeps subtype of skip
\settrue\inlinelefttoright}
\unexpanded\def\spac_directions_righttoleft_hmode
- {\linedir TRT\relax % linedir keeps subtype of skip
+ {\linedirection\directionrighttoleft % linedir keeps subtype of skip
\setfalse\inlinelefttoright}
-% \def\currentdirectionparameters
-% {\ifconditional\inlinelefttoright \else
-% idir {r2l}%
-% \fi
-% \ifconditional\displaylefttoright \else
-% ddir {r2l}%
-% \fi}
-
\unexpanded\def\synchronizelayoutdirection
{\ifconditional\layoutlefttoright
\spac_directions_synchronize_lr
@@ -167,16 +117,17 @@
\def\spac_directions_synchronize_lr
{\settrue\inlinelefttoright
- \textdir TLT\relax
- \pardir TLT\relax}
+ \textdirection\directionlefttoright
+ \pardirection \directionlefttoright}
\def\spac_directions_synchronize_rl
{\setfalse\inlinelefttoright
- \textdir TRT\relax
- \pardir TRT\relax}
+ \textdirection\directionrighttoleft
+ \pardirection \directionrighttoleft}
\unexpanded\def\synchronizeinlinedirection
- {\textdir T\ifconditional\inlinelefttoright L\else R\fi T\relax}
+ {% why not \linedirection here
+ \textdirection\ifconditional\inlinelefttoright\directionlefttoright\else\directionrighttoleft\fi}
\unexpanded\def\checkedlefttoright
{\ifvmode
@@ -210,49 +161,20 @@
\unexpanded\def\usebidiparameter#1%
{\begincsname\??bidi#1\c!bidi\endcsname}
-% maybe some day:
-%
-% \newcount\postdirpenalty % \zerocount
-% \newcount\predirpenalty % \zerocount
-%
-% \def\spac_directions_post_break
-% {\ifhmode
-% \removeunwantedspaces
-% \penalty\postdirpenalty
-% \fi}
-%
-% \def\spac_directions_pre_break
-% {\ifhmode
-% \penalty\predirpenalty
-% \ignorespaces
-% \fi}
-%
-% \unexpanded\def\spac_directions_lefttoright_hmode
-% {\settrue\inlinelefttoright
-% \textdir TLT\relax
-% \aftergroup\spac_directions_post_break
-% \spac_directions_pre_break}
-%
-% \unexpanded\def\spac_directions_righttoleft_hmode
-% {\textdir TRT\relax
-% \setfalse\inlinelefttoright
-% \aftergroup\spac_directions_post_break
-% \spac_directions_pre_break}
-
\unexpanded\def\showdirections
{\dontleavehmode
- \begingroup\infofont\textdir TLT[\space
- layout:\ifconditional \layoutlefttoright l2r\else r2l\fi\space
- display:\ifconditional\displaylefttoright l2r\else r2l\fi\space
- inline:\ifconditional \inlinelefttoright l2r\else r2l\fi\space
+ \begingroup\infofont\textdirection\directionlefttoright[\space
+ layout: \ifconditional\layoutlefttoright l2r\else r2l\fi\space
+ display: \ifconditional\displaylefttoright l2r\else r2l\fi\space
+ inline: \ifconditional\inlinelefttoright l2r\else r2l\fi\space
]\endgroup}
-\unexpanded\def\righttolefthbox#1#{\normalhbox dir TRT #1\bgroup\righttoleft\let\next} \let\rtlhbox\righttolefthbox
-\unexpanded\def\lefttorighthbox#1#{\normalhbox dir TLT #1\bgroup\lefttoright\let\next} \let\ltrhbox\lefttorighthbox
-\unexpanded\def\righttoleftvbox#1#{\normalvbox dir TRT #1\bgroup\righttoleft\let\next} \let\rtlvbox\righttoleftvbox
-\unexpanded\def\lefttorightvbox#1#{\normalvbox dir TLT #1\bgroup\lefttoright\let\next} \let\ltrvbox\lefttorightvbox
-\unexpanded\def\righttoleftvtop#1#{\normalvtop dir TRT #1\bgroup\righttoleft\let\next} \let\rtlvtop\righttoleftvtop
-\unexpanded\def\lefttorightvtop#1#{\normalvtop dir TLT #1\bgroup\lefttoright\let\next} \let\ltrvtop\lefttorightvtop
+\unexpanded\def\righttolefthbox#1#{\reversehbox#1\bgroup\righttoleft\let\next} \let\rtlhbox\righttolefthbox
+\unexpanded\def\lefttorighthbox#1#{\naturalhbox#1\bgroup\lefttoright\let\next} \let\ltrhbox\lefttorighthbox
+\unexpanded\def\righttoleftvbox#1#{\reversevbox#1\bgroup\righttoleft\let\next} \let\rtlvbox\righttoleftvbox
+\unexpanded\def\lefttorightvbox#1#{\naturalvbox#1\bgroup\lefttoright\let\next} \let\ltrvbox\lefttorightvbox
+\unexpanded\def\righttoleftvtop#1#{\reversevtop#1\bgroup\righttoleft\let\next} \let\rtlvtop\righttoleftvtop
+\unexpanded\def\lefttorightvtop#1#{\naturalvtop#1\bgroup\lefttoright\let\next} \let\ltrvtop\lefttorightvtop
\unexpanded\def\autodirhbox#1#{\hbox#1\bgroup\synchronizeinlinedirection\let\next}
\unexpanded\def\autodirvbox#1#{\vbox#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vbox
@@ -355,7 +277,8 @@
\newconstant\c_spac_align_state_par_fill
\def\v_spac_align_fill_amount {\plusone fil}
-\def\v_spac_align_fill_amount_hard {\plusone fill}
+\def\v_spac_align_fill_amount_hard {\plusone fill}
+\def\v_spac_align_fill_amount_extreme {\plustenthousand filll}
\def\v_spac_align_fill_amount_negative {\minusone fil}
\def\v_spac_align_fill_amount_double {\plustwo fil}
\def\v_spac_align_fill_amount_space {\plustwo fil} % can be added to xspace if we have a key
@@ -479,7 +402,8 @@
\spaceskip \zeropoint\relax
\xspaceskip \zeropoint\relax
\parfillskip \zeropoint
- \parfillleftskip\zeropoint\s!plus\v_spac_align_fill_amount_hard\relax
+ \parfillleftskip\zeropoint\s!plus\v_spac_align_fill_amount_extreme\relax
+ \parfillleftmode\plustwo % \plusone checks for multiple lines
\parindent \zeropoint
\relax}
@@ -643,8 +567,8 @@
}}% kept, nice for tracing
\edef\raggedcommand {\the\t_spac_align_collected }%
\edef\updateraggedskips{\spac_align_flush_horizontal}%
- \global\expandafter\let\csname\??alignmentnormalcache\m_spac_align_asked\endcsname\raggedcommand
- \global\expandafter\let\csname\??alignmentraggedcache\m_spac_align_asked\endcsname\updateraggedskips}
+ \expandafter\glet\csname\??alignmentnormalcache\m_spac_align_asked\endcsname\raggedcommand
+ \expandafter\glet\csname\??alignmentraggedcache\m_spac_align_asked\endcsname\updateraggedskips}
\def\spac_align_collect#1%
{\csname\??aligncommand#1\endcsname}
diff --git a/tex/context/base/mkiv/spac-chr.lua b/tex/context/base/mkiv/spac-chr.lua
index 0fa639f92..23cf9741b 100644
--- a/tex/context/base/mkiv/spac-chr.lua
+++ b/tex/context/base/mkiv/spac-chr.lua
@@ -27,9 +27,6 @@ local nodes, node = nodes, node
local nuts = nodes.nuts
-local tonode = nuts.tonode
-local tonut = nuts.tonut
-
local getnext = nuts.getnext
local getprev = nuts.getprev
local getattr = nuts.getattr
@@ -38,7 +35,6 @@ local getlang = nuts.getlang
local setchar = nuts.setchar
local setattrlist = nuts.setattrlist
local getfont = nuts.getfont
-local getchar = nuts.getchar
local setsubtype = nuts.setsubtype
local setdisc = nuts.setdisc
local isglyph = nuts.isglyph
@@ -48,13 +44,13 @@ local setcolor = nodes.tracers.colors.set
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
local remove_node = nuts.remove
-local traverse_id = nuts.traverse_id
-local traverse_char = nuts.traverse_char
+----- traverse_id = nuts.traverse_id
+----- traverse_char = nuts.traverse_char
+local nextchar = nuts.traversers.char
+local nextglyph = nuts.traversers.glyph
local copy_node = nuts.copy
-local tasks = nodes.tasks
-
local nodepool = nuts.pool
local new_penalty = nodepool.penalty
local new_glue = nodepool.glue
@@ -63,12 +59,10 @@ local new_rule = nodepool.rule
local new_disc = nodepool.disc
local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
-local disccodes = nodes.disccodes
+local gluecodes = nodes.gluecodes
local glyph_code = nodecodes.glyph
-local space_skip_code = skipcodes.spaceskip
-local explicit_code = disccodes.explicit
+local spaceskip_code = gluecodes.spaceskip
local chardata = characters.data
local is_punctuation = characters.is_punctuation
@@ -101,8 +95,7 @@ local function inject_quad_space(unicode,head,current,fraction)
setattrlist(glue,current)
setattrlist(current) -- why reset all
setattr(glue,a_character,unicode)
- head, current = insert_node_after(head,current,glue)
- return head, current
+ return insert_node_after(head,current,glue)
end
local function inject_char_space(unicode,head,current,parent)
@@ -112,8 +105,7 @@ local function inject_char_space(unicode,head,current,parent)
setattrlist(glue,current)
setattrlist(current) -- why reset all
setattr(glue,a_character,unicode)
- head, current = insert_node_after(head,current,glue)
- return head, current
+ return insert_node_after(head,current,glue)
end
local function inject_nobreak_space(unicode,head,current,space,spacestretch,spaceshrink)
@@ -132,18 +124,17 @@ local function inject_nobreak_space(unicode,head,current,space,spacestretch,spac
head, current = insert_node_after(head,current,kern)
head, current = insert_node_after(head,current,penalty)
end
- head, current = insert_node_after(head,current,glue)
- return head, current
+ return insert_node_after(head,current,glue)
end
local function nbsp(head,current)
local para = fontparameters[getfont(current)]
if getattr(current,a_alignstate) == 1 then -- flushright
head, current = inject_nobreak_space(0x00A0,head,current,para.space,0,0)
- setsubtype(current,space_skip_code)
+ setsubtype(current,spaceskip_code)
else
head, current = inject_nobreak_space(0x00A0,head,current,para.space,para.spacestretch,para.spaceshrink)
- setsubtype(current,space_skip_code)
+ setsubtype(current,spaceskip_code)
end
return head, current
end
@@ -152,27 +143,13 @@ end
function characters.replacenbsp(head,original)
local head, current = nbsp(head,original)
- head = remove_node(head,original,true)
- return head, current
+ return remove_node(head,original,true)
end
--- function characters.replacenbspaces(head)
--- for current in traverse_id(glyph_code,head) do
--- if getchar(current) == 0x00A0 then
--- local h = nbsp(head,current)
--- if h then
--- head = remove_node(h,current,true)
--- end
--- end
--- end
--- return head
--- end
-
function characters.replacenbspaces(head)
- local head = tonut(head)
local wipe = false
- for current in traverse_id(glyph_code,head) do -- can be anytiem so no traverse_char
- if getchar(current) == 0x00A0 then
+ for current, char, font in nextglyph, head do -- can be anytime so no traverse_char
+ if char == 0x00A0 then
if wipe then
head = remove_node(h,current,true)
wipe = false
@@ -184,15 +161,16 @@ function characters.replacenbspaces(head)
end
end
if wipe then
- head = remove_node(h,current,true)
+ head = remove_node(head,current,true)
end
- return tonode(head)
+ return head
end
-- This initialization might move someplace else if we need more of it. The problem is that
-- this module depends on fonts so we have an order problem.
local nbsphash = { } setmetatableindex(nbsphash,function(t,k)
+ -- this needs checking !
for i=unicodeblocks.devanagari.first,unicodeblocks.devanagari.last do nbsphash[i] = true end
for i=unicodeblocks.kannada .first,unicodeblocks.kannada .last do nbsphash[i] = true end
setmetatableindex(nbsphash,nil)
@@ -209,11 +187,11 @@ local methods = {
[0x001F] = function(head,current) -- kind of special
local next = getnext(current)
if next then
- local char = isglyph(next)
+ local char, font = isglyph(next)
if char then
head, current = remove_node(head,current,true)
if not is_punctuation[char] then
- local p = fontparameters[getfont(next)]
+ local p = fontparameters[font]
head, current = insert_node_before(head,current,new_glue(p.space,p.space_stretch,p.space_shrink))
end
end
@@ -319,9 +297,7 @@ local methods = {
characters.methods = methods
-- function characters.handler(head) -- todo: use traverse_id
--- head = tonut(head)
-- local current = head
--- local done = false
-- while current do
-- local char, id = isglyph(current)
-- if char then
@@ -335,47 +311,39 @@ characters.methods = methods
-- if h then
-- head = remove_node(h,current,true)
-- end
--- done = true
-- end
-- current = next
-- else
-- current = getnext(current)
-- end
-- end
--- return tonode(head), done
+-- return head
-- end
--- for current, char, font in traverse_char_data(head) will save 0.015 on a 300 page doc
-
-- this also works ok in math as we run over glyphs and these stay glyphs ... not sure
-- about scripts and such but that is not important anyway ... some day we can consider
-- special definitions in math
function characters.handler(head)
- local head = tonut(head)
local wipe = false
- for current in traverse_char(head) do
- local char = getchar(current)
- if char then
- local method = methods[char]
- if method then
- if wipe then
- head = remove_node(head,wipe,true)
- wipe = false
- end
- if trace_characters then
- report_characters("replacing character %C, description %a",char,lower(chardata[char].description))
- end
- local h = method(head,current)
- if h then
- wipe = current
- end
- done = true
+ for current, char in nextchar, head do
+ local method = methods[char]
+ if method then
+ if wipe then
+ head = remove_node(head,wipe,true)
+ wipe = false
+ end
+ if trace_characters then
+ report_characters("replacing character %C, description %a",char,lower(chardata[char].description))
+ end
+ local h = method(head,current)
+ if h then
+ wipe = current
end
end
end
if wipe then
head = remove_node(head,wipe,true)
end
- return tonode(head), done
+ return head
end
diff --git a/tex/context/base/mkiv/spac-chr.mkiv b/tex/context/base/mkiv/spac-chr.mkiv
index ed2cb47f9..23f4ac8dd 100644
--- a/tex/context/base/mkiv/spac-chr.mkiv
+++ b/tex/context/base/mkiv/spac-chr.mkiv
@@ -15,7 +15,7 @@
\unprotect
-\registerctxluafile{spac-chr}{}
+\registerctxluafile{spac-chr}{optimize}
\definesystemattribute[characters][public]
diff --git a/tex/context/base/mkiv/spac-flr.mkiv b/tex/context/base/mkiv/spac-flr.mkiv
index 29351a3dd..bd50bfea6 100644
--- a/tex/context/base/mkiv/spac-flr.mkiv
+++ b/tex/context/base/mkiv/spac-flr.mkiv
@@ -60,6 +60,35 @@
\endgroup
\ignorespaces}
+% \definefiller
+% [MyFiller]
+% [offset=.25\emwidth,
+% rightmargindistance=-\rightskip,
+% method=middle]
+%
+% \startitemize[packed,joinedup][rightmargin=5em]
+% \startitem
+% \input sapolsky \fillupto[MyFiller]{RS}
+% \stopitem
+% \stopitemize
+
+\unexpanded\def\fillupto
+ {\dosingleempty\spac_fillers_upto}
+
+\def\spac_fillers_upto[#1]#2%
+ {\removeunwantedspaces
+ \begingroup
+ \edef\currentfiller{#1}%
+ \scratchdimen\dimexpr\fillerparameter\c!rightmargindistance\relax
+ \ifdim\scratchdimen=\zeropoint\else
+ \parfillskip \scratchdimen\s!plus \plusone\s!fil\relax
+ \fi
+ \spac_fillers_indeed[#1]%
+ \doifsomething{#2}{\hbox{#2}}%
+ \par
+ \endgroup
+ \ignorespaces}
+
\setvalue{\??filleralternative\s!unknown}%
{}
@@ -87,8 +116,8 @@
\setvalue{\??filleralternative\v!rule}%
{\expandnamespaceparameter\??fillerleadermethod\fillerparameter\c!method\v!local
\hrule
- \!!height\fillerparameter\c!height
- \!!depth \fillerparameter\c!depth
+ \s!height\fillerparameter\c!height
+ \s!depth \fillerparameter\c!depth
\hfill}
\letvalue{\??fillerleadermethod\s!local }\normalleaders % overflow ends up inbetween (current box)
@@ -106,6 +135,7 @@
\c!depth=\zeropoint,
\c!leftmargin=\zeropoint,
\c!rightmargin=\zeropoint,
+ \c!rightmargindistance=\zeropoint,
\c!alternative=\v!symbol,
\c!method=\s!local]
diff --git a/tex/context/base/mkiv/spac-grd.mkiv b/tex/context/base/mkiv/spac-grd.mkiv
index 73c6e0dd1..72d017836 100644
--- a/tex/context/base/mkiv/spac-grd.mkiv
+++ b/tex/context/base/mkiv/spac-grd.mkiv
@@ -108,8 +108,8 @@
\newbox \b_spac_lines_correction_after
\def\spac_lines_initialize_corrections
- {\setbox\b_spac_lines_correction_before\hbox{\setstrut\strut}%
- \setbox\b_spac_lines_correction_after \hbox{(}%
+ {\setbox\b_spac_lines_correction_before\hpack{\setstrut\strut}%
+ \setbox\b_spac_lines_correction_after \hbox {(}%
\d_spac_lines_correction_before\dimexpr\ht\b_spac_lines_correction_before-\ht\b_spac_lines_correction_after\relax
\d_spac_lines_correction_after \dimexpr\dp\b_spac_lines_correction_before-\dp\b_spac_lines_correction_after\relax
\ifdim\d_spac_lines_correction_before<\zeropoint\d_spac_lines_correction_before\zeropoint\fi
diff --git a/tex/context/base/mkiv/spac-hor.mkiv b/tex/context/base/mkiv/spac-hor.mkiv
index ce747a202..32b7f06fb 100644
--- a/tex/context/base/mkiv/spac-hor.mkiv
+++ b/tex/context/base/mkiv/spac-hor.mkiv
@@ -17,8 +17,9 @@
\registerctxluafile{spac-hor}{}
-\let \parfillrightskip \parfillskip
-\newskip\parfillleftskip
+\let \parfillrightskip \parfillskip
+\newskip \parfillleftskip
+\newconstant\parfillleftmode
\let\v_spac_indentation_current\empty % amount/keyword
@@ -205,6 +206,9 @@
\let\checkindentation\relax
+\installmacrostack\checkindentation
+\installmacrostack\ifindentation
+
\def\spac_indentation_remove
{\ifdim\parindent=\zeropoint \else
\begingroup
@@ -218,21 +222,21 @@
\def\spac_indentation_do_toggle_indeed
{\global\indentationfalse
- \global\let\checkindentation\spac_indentation_no_toggle_indeed
+ \glet\checkindentation\spac_indentation_no_toggle_indeed
\spac_indentation_remove}
\def\spac_indentation_no_toggle_indeed
{\global\indentationtrue
- \global\let\checkindentation\spac_indentation_do_toggle_indeed}
+ \glet\checkindentation\spac_indentation_do_toggle_indeed}
\def\spac_indentation_do_indeed
{\global\indentationtrue}
\def\spac_indentation_do_toggle
- {\global\let\checkindentation\spac_indentation_do_toggle_indeed}
+ {\glet\checkindentation\spac_indentation_do_toggle_indeed}
\def\spac_indentation_no_toggle
- {\global\let\checkindentation\spac_indentation_no_toggle_indeed}
+ {\glet\checkindentation\spac_indentation_no_toggle_indeed}
\def\spac_indentation_check_toggle
{\ifcase\c_spac_indentation_toggle_state
@@ -244,22 +248,22 @@
\fi}
\def\spac_indentation_variant_yes
- {\global\let\checkindentation\spac_indentation_do_indeed}
+ {\glet\checkindentation\spac_indentation_do_indeed}
\def\spac_indentation_no_next_check
{\spac_indentation_remove
- \global\let\checkindentation\spac_indentation_do_indeed}
+ \glet\checkindentation\spac_indentation_do_indeed}
\def\spac_indentation_variant_no % made global
{\ifinpagebody \else
\global\indentationfalse
- \global\let\checkindentation\spac_indentation_no_next_check
+ \glet\checkindentation\spac_indentation_no_next_check
\fi}
\def\nonoindentation % bv bij floats
{\ifinpagebody \else
\global\indentationtrue
- \global\let\checkindentation\spac_indentation_do_indeed
+ \glet\checkindentation\spac_indentation_do_indeed
\fi}
\def\spac_indentation_variant_force
@@ -271,13 +275,13 @@
\fi \fi}
\appendtoks
- \pushmacro\checkindentation
- \pushmacro\ifindentation
+ \push_macro_checkindentation
+ \push_macro_ifindentation
\to \everypushsomestate
\appendtoks
- \popmacro\ifindentation
- \popmacro\checkindentation
+ \pop_macro_ifindentation
+ \pop_macro_checkindentation
\to \everypopsomestate
% public:
@@ -287,16 +291,16 @@
\let\doindentation\spac_indentation_variant_yes % public
\def\dontrechecknextindentation % public (in macros)
- {\global\let\dorechecknextindentation\relax}
+ {\glet\dorechecknextindentation\relax}
\let\dorechecknextindentation\relax % public (in macros)
\unexpanded\def\spac_indentation_check_next_indentation
- {\global\let\dorechecknextindentation\relax
+ {\glet\dorechecknextindentation\relax
\doifelsenextchar\par\donothing\spac_indentation_variant_no} % messy check as next is seldom \par
\def\spac_indentation_variant_auto
- {\global\let\dorechecknextindentation\spac_indentation_check_next_indentation}
+ {\glet\dorechecknextindentation\spac_indentation_check_next_indentation}
%D This one sets up the local indentation behaviour (i.e. either or not
%D a next paragraph will be indented).
@@ -564,6 +568,13 @@
\fi
\fi}
+\unexpanded\def\onlynonbreakablespace
+ {\ifdim\lastskip=\interwordspace
+ \unskip
+ \nonbreakablespace
+ \fi
+ \ignorespaces}
+
% \startbuffer
% \startlines \tt \fixedspaces
% 0~1~~2~~~3~~~~4~~~~~5
@@ -598,12 +609,15 @@
\ifdefined\quad \else
- \unexpanded\def\enskip{\hskip.5\emwidth}
- \unexpanded\def\quad {\hskip \emwidth}
- \unexpanded\def\qquad {\hskip 2\emwidth}
+ \unexpanded\def\enskip{\hskip.5\emwidth\relax}
+ \unexpanded\def\quad {\hskip \emwidth\relax}
+ \unexpanded\def\qquad {\hskip 2\emwidth\relax}
\fi
+\unexpanded\def\negenspace{\kern-.5\emwidth}
+\unexpanded\def\negemspace{\kern- \emwidth}
+
\let\emspace\quad
\unexpanded\def\charspace{ } % the unexpandable \space (as space can also be delimiter for numbers)
@@ -1116,6 +1130,8 @@
\unexpanded\def\spac_spaces_checked_normal {\mathortext\normalspace{\dontleavehmode\normalspace}}%
\unexpanded\def\spac_spaces_checked_fixed {\mathortext\normalspace{\dontleavehmode\fixedspace}}%
+% hm, order matters when we \let in \obeyspaces
+
\installspacemethod \v!on
{\obeyspaces
\let\obeyedspace\spac_spaces_checked_control
diff --git a/tex/context/base/mkiv/spac-lin.mkiv b/tex/context/base/mkiv/spac-lin.mkiv
index 6558cb111..d862f6d81 100644
--- a/tex/context/base/mkiv/spac-lin.mkiv
+++ b/tex/context/base/mkiv/spac-lin.mkiv
@@ -86,7 +86,7 @@
\let\spac_lines_break\relax
\fi
\linesparameter\c!before
- \pushmacro\checkindentation
+ \push_macro_checkindentation
\whitespace
\dostarttaggedchained\t!lines\currentlines\??lines
\begingroup
@@ -126,7 +126,7 @@
{\dostoptagged
\endgroup
\dostoptagged
- \popmacro\checkindentation
+ \pop_macro_checkindentation
\linesparameter\c!after
\egroup}
diff --git a/tex/context/base/mkiv/spac-pag.mkiv b/tex/context/base/mkiv/spac-pag.mkiv
index c7d22f0e0..9adc591ed 100644
--- a/tex/context/base/mkiv/spac-pag.mkiv
+++ b/tex/context/base/mkiv/spac-pag.mkiv
@@ -151,6 +151,7 @@
\unexpanded\def\signalrightpage {\dotrackpagestate \s!paragraph\nofraggedparagraphs} % use \dontleavehmode if needed
\unexpanded\def\doifelserightpage{\doifelserightpagestate\s!paragraph\nofraggedparagraphs}
+\unexpanded\def\rightpageorder {\pagestaterealpageorder\s!paragraph\nofraggedparagraphs}
\let\doifrightpageelse\doifelserightpage
@@ -169,9 +170,9 @@
\fi
\ifpagechanged
\letgvalue{\??pagechanges#2:#1}\m_spac_pagestates_realpage
- \globallet\lastchangedpage\m_spac_pagestates_realpage
+ \glet\lastchangedpage\m_spac_pagestates_realpage
\else
- \globallet\lastchangedpage\realfolio
+ \glet\lastchangedpage\realfolio
\fi}
\def\changedpagestate#1#2%
diff --git a/tex/context/base/mkiv/spac-par.mkiv b/tex/context/base/mkiv/spac-par.mkiv
index 4dd3db243..0932b7359 100644
--- a/tex/context/base/mkiv/spac-par.mkiv
+++ b/tex/context/base/mkiv/spac-par.mkiv
@@ -79,17 +79,17 @@
\setvalue{\??paragraphintro\v!first}#1%
{\global\settrue\c_spac_paragraphs_intro_first
- \global\t_spac_paragraphs_intro_first\expandafter{\the\t_spac_paragraphs_intro_first#1}%
+ \gtoksapp\t_spac_paragraphs_intro_first{#1}%
\glet\insertparagraphintro\spac_paragraphs_flush_intro}
\setvalue{\??paragraphintro\v!next}#1%
{\global\settrue\c_spac_paragraphs_intro_next
- \global\t_spac_paragraphs_intro_next\expandafter{\the\t_spac_paragraphs_intro_next#1}%
+ \gtoksapp\t_spac_paragraphs_intro_next{#1}%
\glet\insertparagraphintro\spac_paragraphs_flush_intro}
\setvalue{\??paragraphintro\v!each}#1%
{\global\settrue\c_spac_paragraphs_intro_each
- \global\t_spac_paragraphs_intro_each\expandafter{\the\t_spac_paragraphs_intro_each#1}%
+ \gtoksapp\t_spac_paragraphs_intro_each{#1}%
\glet\insertparagraphintro\spac_paragraphs_flush_intro}
%D We can say:
@@ -130,7 +130,7 @@
\unexpanded\def\flushatparagraph#1%
{\global\c_spac_paragraphs_intro_first\plusone
- \global\t_spac_paragraphs_intro_first\expandafter{\the\t_spac_paragraphs_intro_first#1}%
+ \gtoksapp\t_spac_paragraphs_intro_first{#1}%
\glet\insertparagraphintro\spac_paragraphs_flush_intro}
%D Here comes the flusher (we misuse the one level expansion of token
@@ -221,19 +221,19 @@
\dowithnextboxcs\spac_postponed_data_finish\hbox}
\def\spac_postponed_data_finish
- {\global\setbox\b_spac_postponed_data\hbox % to\zeropoint
+ {\global\setbox\b_spac_postponed_data\hpack % to\zeropoint
{\box\b_spac_postponed_data\box\nextbox}%
\endgroup}
\def\spac_postponed_data_flush
{%\iftrialtypesetting \else
\ifvoid\b_spac_postponed_data\else
- \hbox{\smashedbox\b_spac_postponed_data}% \box\b_spac_postponed_data
+ \hpack{\smashedbox\b_spac_postponed_data}% \box\b_spac_postponed_data
\fi
\glet\flushpostponednodedata\relax
}%\fi}
-\unexpanded\def\doflushatpar
+\unexpanded\def\doflushatpar % might be renamed
{\ifvmode
\expandafter\flushatnextpar
\else
diff --git a/tex/context/base/mkiv/spac-prf.lua b/tex/context/base/mkiv/spac-prf.lua
index a28f30593..32582c56f 100644
--- a/tex/context/base/mkiv/spac-prf.lua
+++ b/tex/context/base/mkiv/spac-prf.lua
@@ -17,6 +17,7 @@ local formatters = string.formatters
local nodecodes = nodes.nodecodes
local gluecodes = nodes.gluecodes
local listcodes = nodes.listcodes
+local leadercodes = nodes.leadercodes
local glyph_code = nodecodes.glyph
local disc_code = nodecodes.disc
@@ -30,10 +31,12 @@ local math_code = nodecodes.math
local rule_code = nodecodes.rule
local marginkern_code = nodecodes.marginkern
-local leaders_code = gluecodes.leaders
+local leaders_code = leadercodes.leaders
+
local lineskip_code = gluecodes.lineskip
local baselineskip_code = gluecodes.baselineskip
-local line_code = listcodes.line
+
+local linelist_code = listcodes.line
local texlists = tex.lists
local settexattribute = tex.setattribute
@@ -128,6 +131,9 @@ local function getprofile(line,step)
local margin = step / 4
local min = 0
local max = ceiling(getwidth(line)/step) + 1
+ local wd = 0
+ local ht = 0
+ local dp = 0
for i=min,max do
heights[i] = 0
@@ -136,8 +142,6 @@ local function getprofile(line,step)
-- remember p
- local wd, ht, dp = 0, 0, 0
-
local function progress()
position = width
width = position + wd
@@ -639,7 +643,7 @@ end
local function profilelist(line,mvl)
- local current = tonut(line)
+ local current = line
local top = nil
local bot = nil
@@ -668,7 +672,7 @@ local function profilelist(line,mvl)
local id = getid(current)
if id == hlist_code then
local subtype = getsubtype(current)
- if subtype == line_code then
+ if subtype == linelist_code then
t_profile = hasprofile(current)
if t_profile then
top = current
@@ -710,7 +714,7 @@ local function profilelist(line,mvl)
if id == hlist_code then -- check subtype
local subtype = getsubtype(current)
- if subtype == line_code then
+ if subtype == linelist_code then
if top == current then
-- skip
bot = nil -- to be sure
@@ -819,7 +823,7 @@ function profiling.profilebox(specification)
local id = getid(current)
if id == hlist_code then
local subtype = getsubtype(current)
- if subtype == line_code then
+ if subtype == linelist_code then
if top then
bot = current
b_profile = setprofile(bot)
@@ -899,9 +903,8 @@ end
--
-- function profiling.vboxhandler(head,where)
-- if head and not ignore[where] then
--- local h = tonut(head)
--- if getnext(h) then
--- profilelist(h)
+-- if getnext(head) then
+-- profilelist(head)
-- end
-- end
-- return head
@@ -911,7 +914,7 @@ function profiling.pagehandler(head)
if head then
profilelist(head,true)
end
- return head, true
+ return head
end
interfaces.implement {
diff --git a/tex/context/base/mkiv/spac-ver.lua b/tex/context/base/mkiv/spac-ver.lua
index 969a195e1..b55f1ca7c 100644
--- a/tex/context/base/mkiv/spac-ver.lua
+++ b/tex/context/base/mkiv/spac-ver.lua
@@ -116,8 +116,8 @@ local a_snapmethod = attributes.private('snapmethod')
local a_snapvbox = attributes.private('snapvbox')
local nuts = nodes.nuts
-local tonode = nuts.tonode
local tonut = nuts.tonut
+local tonode = nuts.tonode
local getnext = nuts.getnext
local setlink = nuts.setlink
@@ -147,15 +147,16 @@ local getdepth = nuts.getdepth
local find_node_tail = nuts.tail
local flush_node = nuts.flush_node
-local traverse_nodes = nuts.traverse
-local traverse_nodes_id = nuts.traverse_id
local insert_node_after = nuts.insert_after
local insert_node_before = nuts.insert_before
local remove_node = nuts.remove
local count_nodes = nuts.countall
local hpack_node = nuts.hpack
local vpack_node = nuts.vpack
------ writable_spec = nuts.writable_spec
+
+local nextnode = nuts.traversers.node
+local nexthlist = nuts.traversers.hlist
+
local nodereference = nuts.reference
local theprop = nuts.theprop
@@ -170,8 +171,9 @@ local new_kern = nodepool.kern
local new_rule = nodepool.rule
local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
-local penaltycodes = nodes.penaltycodes
+local gluecodes = nodes.gluecodes
+----- penaltycodes = nodes.penaltycodes
+----- listcodes = nodes.listcodes
local penalty_code = nodecodes.penalty
local kern_code = nodecodes.kern
@@ -179,21 +181,22 @@ local glue_code = nodecodes.glue
local insert_code = nodecodes.ins
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
+local rule_code = nodecodes.rule
local localpar_code = nodecodes.localpar
-local linebreak_code = penaltycodes.linebreakpenalty
+local userskip_code = gluecodes.userskip
+local lineskip_code = gluecodes.lineskip
+local baselineskip_code = gluecodes.baselineskip
+local parskip_code = gluecodes.parskip
+local topskip_code = gluecodes.topskip
+local splittopskip_code = gluecodes.splittopskip
-local userskip_code = skipcodes.userskip
-local lineskip_code = skipcodes.lineskip
-local baselineskip_code = skipcodes.baselineskip
-local parskip_code = skipcodes.parskip
-local topskip_code = skipcodes.topskip
-local splittopskip_code = skipcodes.splittopskip
+local linelist_code = nodes.listcodes.line
-local abovedisplayskip_code = skipcodes.abovedisplayskip
-local belowdisplayskip_code = skipcodes.belowdisplayskip
-local abovedisplayshortskip_code = skipcodes.abovedisplayshortskip
-local belowdisplayshortskip_code = skipcodes.belowdisplayshortskip
+local abovedisplayskip_code = gluecodes.abovedisplayskip
+local belowdisplayskip_code = gluecodes.belowdisplayskip
+local abovedisplayshortskip_code = gluecodes.abovedisplayshortskip
+local belowdisplayshortskip_code = gluecodes.belowdisplayshortskip
local properties = nodes.properties.data
@@ -208,90 +211,93 @@ vspacingdata.snapmethods = snapmethods
storage.register("builders/vspacing/data/snapmethods", snapmethods, "builders.vspacing.data.snapmethods")
-local default = {
- [v_maxheight] = true,
- [v_maxdepth] = true,
- [v_strut] = true,
- [v_hfraction] = 1,
- [v_dfraction] = 1,
- [v_bfraction] = 0.25,
-}
+do
-local fractions = {
- [v_minheight] = v_hfraction, [v_maxheight] = v_hfraction,
- [v_mindepth] = v_dfraction, [v_maxdepth] = v_dfraction,
- [v_box] = v_bfraction,
- [v_top] = v_tlines, [v_bottom] = v_blines,
-}
+ local default = {
+ [v_maxheight] = true,
+ [v_maxdepth] = true,
+ [v_strut] = true,
+ [v_hfraction] = 1,
+ [v_dfraction] = 1,
+ [v_bfraction] = 0.25,
+ }
-local values = {
- offset = "offset"
-}
+ local fractions = {
+ [v_minheight] = v_hfraction, [v_maxheight] = v_hfraction,
+ [v_mindepth] = v_dfraction, [v_maxdepth] = v_dfraction,
+ [v_box] = v_bfraction,
+ [v_top] = v_tlines, [v_bottom] = v_blines,
+ }
-local colonsplitter = lpeg.splitat(":")
+ local values = {
+ offset = "offset"
+ }
-local function listtohash(str)
- local t = { }
- for s in gmatch(str,"[^, ]+") do
- local key, detail = lpegmatch(colonsplitter,s)
- local v = variables[key]
- if v then
- t[v] = true
- if detail then
- local k = fractions[key]
- if k then
- detail = tonumber("0" .. detail)
- if detail then
- t[k] = detail
- end
- else
- k = values[key]
+ local colonsplitter = lpeg.splitat(":")
+
+ local function listtohash(str)
+ local t = { }
+ for s in gmatch(str,"[^, ]+") do
+ local key, detail = lpegmatch(colonsplitter,s)
+ local v = variables[key]
+ if v then
+ t[v] = true
+ if detail then
+ local k = fractions[key]
if k then
- detail = todimen(detail)
+ detail = tonumber("0" .. detail)
if detail then
t[k] = detail
end
+ else
+ k = values[key]
+ if k then
+ detail = todimen(detail)
+ if detail then
+ t[k] = detail
+ end
+ end
end
end
+ else
+ detail = tonumber("0" .. key)
+ if detail then
+ t[v_hfraction] = detail
+ t[v_dfraction] = detail
+ end
end
+ end
+ if next(t) then
+ t[v_hfraction] = t[v_hfraction] or 1
+ t[v_dfraction] = t[v_dfraction] or 1
+ return t
else
- detail = tonumber("0" .. key)
- if detail then
- t[v_hfraction] = detail
- t[v_dfraction] = detail
- end
+ return default
end
end
- if next(t) then
- t[v_hfraction] = t[v_hfraction] or 1
- t[v_dfraction] = t[v_dfraction] or 1
- return t
- else
- return default
+
+ function vspacing.definesnapmethod(name,method)
+ local n = #snapmethods + 1
+ local t = listtohash(method)
+ snapmethods[n] = t
+ t.name = name -- not interfaced
+ t.specification = method -- not interfaced
+ context(n)
end
-end
-function vspacing.definesnapmethod(name,method)
- local n = #snapmethods + 1
- local t = listtohash(method)
- snapmethods[n] = t
- t.name = name -- not interfaced
- t.specification = method -- not interfaced
- context(n)
end
local function validvbox(parentid,list)
if parentid == hlist_code then
local id = getid(list)
- if id == localpar_code then -- check for initial par subtype
+ if id == localpar_code and getsubtype(list) == 0 then
list = getnext(list)
if not next then
return nil
end
end
local done = nil
- for n in traverse_nodes(list) do
- local id = getid(n)
+ for n, id in nextnode, list do
if id == vlist_code or id == hlist_code then
if done then
return nil
@@ -320,14 +326,13 @@ local function already_done(parentid,list,a_snapmethod) -- todo: done when only
-- problem: any snapped vbox ends up in a line
if list and parentid == hlist_code then
local id = getid(list)
- if id == localpar_code then -- check for initial par subtype
+ if id == localpar_code and getsubtype(list) == 0 then
list = getnext(list)
if not list then
return false
end
end
- for n in traverse_nodes(list) do
- local id = getid(n)
+ for n, id in nextnode, list do
if id == hlist_code or id == vlist_code then
-- local a = getattr(n,a_snapmethod)
-- if not a then
@@ -536,7 +541,7 @@ local function snap_hlist(where,current,method,height,depth) -- method[v_strut]
if thebox and id == vlist_code then
local list = getlist(thebox)
local lw, lh, ld
- for n in traverse_nodes_id(hlist_code,list) do
+ for n in nexthlist, list do
lw, lh, ld = getwhd(n)
break
end
@@ -572,7 +577,7 @@ local function snap_hlist(where,current,method,height,depth) -- method[v_strut]
if thebox and id == vlist_code then
local list = getlist(thebox)
local lw, lh, ld
- for n in traverse_nodes_id(hlist_code,list) do
+ for n in nexthlist, list do
lw, lh, ld = getwhd(n)
end
if lh then
@@ -872,14 +877,15 @@ end
local trace_list, tracing_info, before, after = { }, false, "", ""
local function nodes_to_string(head)
- local current, t = head, { }
+ local current = head
+ local t = { }
while current do
local id = getid(current)
local ty = nodecodes[id]
if id == penalty_code then
t[#t+1] = formatters["%s:%s"](ty,getpenalty(current))
elseif id == glue_code then
- t[#t+1] = formatters["%s:%s:%p"](ty,skipcodes[getsubtype(current)],getwidth(current))
+ t[#t+1] = formatters["%s:%s:%p"](ty,gluecodes[getsubtype(current)],getwidth(current))
elseif id == kern_code then
t[#t+1] = formatters["%s:%p"](ty,getkern(current))
else
@@ -1261,17 +1267,26 @@ do
if trace then
reset_tracing(head)
end
- local current, oldhead = head, head
- local glue_order, glue_data, force_glue = 0, nil, false
- local penalty_order, penalty_data, natural_penalty, special_penalty = 0, nil, nil, nil
- local parskip, ignore_parskip, ignore_following, ignore_whitespace, keep_together = nil, false, false, false, false
- local lastsnap = nil
+ local current = head
+ local oldhead = head
+ local glue_order = 0
+ local glue_data
+ local force_glue = false
+ local penalty_order = 0
+ local penalty_data
+ local natural_penalty
+ local special_penalty
+ local parskip
+ local ignore_parskip = false
+ local ignore_following = false
+ local ignore_whitespace = false
+ local keep_together = false
+ local lastsnap
+ local pagehead
+ local pagetail
--
-- todo: keep_together: between headers
--
- local pagehead = nil
- local pagetail = nil
-
local function getpagelist()
if not pagehead then
pagehead = texlists.page_head
@@ -1396,7 +1411,7 @@ do
end
head = insert_node_before(head,current,glue_data)
else
- -- report_vspacing("needs checking (%s): %p",skipcodes[getsubtype(glue_data)],w)
+ -- report_vspacing("needs checking (%s): %p",gluecodes[getsubtype(glue_data)],w)
flush_node(glue_data)
end
end
@@ -1814,7 +1829,7 @@ do
if snap and trace_vsnapping then
local w = getwidth(current)
if w ~= 0 then
- report_snapper("glue %p of type %a kept",w,skipcodes[subtype])
+ report_snapper("glue %p of type %a kept",w,gluecodes[subtype])
end
end
if trace then
@@ -1881,7 +1896,7 @@ do
trace_info("head has been changed from %a to %a",nodecodes[getid(oldhead)],nodecodes[getid(head)])
end
end
- return head, true
+ return head
end
-- alignment after_output end box new_graf vmode_par hmode_par insert penalty before_display after_display
@@ -1909,43 +1924,47 @@ do
-- ugly code: we get partial lists (check if this stack is still okay) ... and we run
-- into temp nodes (sigh)
+ local forceflush = false
+
function vspacing.pagehandler(newhead,where)
-- local newhead = texlists.contrib_head
if newhead then
- newhead = tonut(newhead)
local newtail = find_node_tail(newhead) -- best pass that tail, known anyway
local flush = false
stackhack = true -- todo: only when grid snapping once enabled
-- todo: fast check if head = tail
- for n in traverse_nodes(newhead) do -- we could just look for glue nodes
- local id = getid(n)
+ for n, id, subtype in nextnode, newhead do -- we could just look for glue nodes
if id ~= glue_code then
flush = true
- else
- local subtype = getsubtype(n)
- if subtype == userskip_code then
- if getattr(n,a_skipcategory) then
- stackhack = true
- else
- flush = true
- end
- elseif subtype == parskip_code then
- -- if where == new_graf then ... end
- if texgetcount("c_spac_vspacing_ignore_parskip") > 0 then
--- texsetcount("c_spac_vspacing_ignore_parskip",0)
- setglue(n)
- -- maybe removenode
- end
+ elseif subtype == userskip_code then
+ if getattr(n,a_skipcategory) then
+ stackhack = true
+ else
+ flush = true
+ end
+ elseif subtype == parskip_code then
+ -- if where == new_graf then ... end
+ if texgetcount("c_spac_vspacing_ignore_parskip") > 0 then
+ -- texsetcount("c_spac_vspacing_ignore_parskip",0)
+ setglue(n)
+ -- maybe removenode
end
end
end
texsetcount("c_spac_vspacing_ignore_parskip",0)
+
+ if forceflush then
+ forceflush = false
+ flush = true
+ end
+
if flush then
if stackhead then
if trace_collect_vspacing then report("%s > appending %s nodes to stack (final): %s",where,newhead) end
setlink(stacktail,newhead)
- newhead = stackhead
- stackhead, stacktail = nil, nil
+ newhead = stackhead
+ stackhead = nil
+ stacktail = nil
end
if stackhack then
stackhack = false
@@ -1956,7 +1975,7 @@ do
if trace_collect_vspacing then report("%s > flushing %s nodes: %s",where,newhead) end
-- texlists.contrib_head = newhead
end
- return tonode(newhead)
+ return newhead
else
if stackhead then
if trace_collect_vspacing then report("%s > appending %s nodes to stack (intermediate): %s",where,newhead) end
@@ -1966,13 +1985,43 @@ do
stackhead = newhead
end
stacktail = newtail
- -- texlists.contrib_head = nil
- -- newhead = nil
end
end
return nil
end
+ -- function vspacing.flushpagestack()
+ -- if stackhead then
+ -- local head = texlists.contrib_head
+ -- if head then
+ -- local tail = find_node_tail(head)
+ -- setlink(tail,stackhead)
+ -- else
+ -- texlists.contrib_head = tonode(stackhead)
+ -- end
+ -- stackhead, stacktail = nil, nil
+ -- end
+ --
+ -- end
+
+ function vspacing.pageoverflow()
+ local h = 0
+ if stackhead then
+ for n, id in nextnode, stackhead do
+ if id == glue_code then
+ h = h + getwidth(n)
+ elseif id == kern_code then
+ h = h + getkern(n)
+ end
+ end
+ end
+ return h
+ end
+
+ function vspacing.forcepageflush()
+ forceflush = true
+ end
+
local ignore = table.tohash {
"split_keep",
"split_off",
@@ -1980,11 +2029,10 @@ do
}
function vspacing.vboxhandler(head,where)
- if head and not ignore[where] then
- local h = tonut(head)
- if getnext(h) then -- what if a one liner and snapping?
- h = collapser(h,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper
- return tonode(h)
+ if head and not ignore[where] and getnext(head) then
+ if getnext(head) then -- what if a one liner and snapping?
+ head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper
+ return head
end
end
return head
@@ -2015,7 +2063,6 @@ do
local outer = texnest[0]
local enabled = true
- local count = true
local trace = false
local report = logs.reporter("vspacing")
@@ -2024,96 +2071,84 @@ do
end)
directives.register("vspacing.synchronizepage",function(v)
- if v == true or v == "count" then
- enabled = true
- count = true
- elseif v == "first" then
- enabled = true
- count = false
- else
- enabled = false
- count = false
- end
+ enabled = v
end)
- -- hm, check the old one
+ local ignoredepth = -65536000
- -- function vspacing.synchronizepage()
- -- if enabled then
- -- local head = texlists.hold_head
- -- local skip = 0
- -- while head and head.id == insert_code do
- -- head = head.next
- -- skip = skip + 1
- -- end
- -- if head then
- -- outer.prevdepth = 0
- -- end
- -- if trace then
- -- report("prevdepth %s at page %i, skipped %i, value %p",
- -- head and "reset" or "kept",texgetcount("realpageno"),skip,outer.prevdepth)
- -- end
- -- end
- -- end
+ -- A previous version analyzed the number of lines moved to the next page in
+ -- synchronizepage because prevgraf is unreliable in that case. However, we cannot
+ -- tweak that parameter because it is also used in postlinebreak and hangafter, so
+ -- there is a danger for interference. Therefore we now do it dynamically.
- local ignoredepth = -65536000
+ -- We can also support other lists but there prevgraf probably is ok.
- function vspacing.synchronizepage()
+ function vspacing.getnofpreviouslines(head)
if enabled then
- local newdepth = outer.prevdepth
- local olddepth = newdepth
- local oldlines = outer.prevgraf
- local newlines = 0
- local boxfound = false
- local head = texlists.contrib_head
+ if not thead then
+ head = texlists.page_head
+ end
+ local noflines = 0
if head then
local tail = find_node_tail(tonut(head))
while tail do
local id = getid(tail)
if id == hlist_code then
- if not boxfound then
- newdepth = getdepth(tail)
- boxfound = true
- end
- newlines = newlines + 1
- if not count then
+ if getsubtype(tail) == linelist_code then
+ noflines = noflines + 1
+ else
break
end
elseif id == vlist_code then
- if not boxfound then
- newdepth = getdepth(tail)
- boxfound = true
- end
break
elseif id == glue_code then
local subtype = getsubtype(tail)
- if not (subtype == baselineskip_code or subtype == lineskip_code) then
- break
- elseif boxfound and not count then
- break
+ if subtype == baselineskip_code or subtype == lineskip_code then
+ -- we're ok
+ elseif subtype == parskip_code then
+ if getwidth(tail) > 0 then
+ break
+ else
+ -- we assume we're ok
+ end
end
elseif id == penalty_code then
- if boxfound and not count then
- break
- end
- else
- -- ins, mark, kern, rule, boundary, whatsit
+ -- we're probably ok
+ elseif id == rule_code or id == kern_code then
break
+ else
+ -- ins, mark, boundary, whatsit
end
tail = getprev(tail)
end
end
- if boxfound then
- -- what if newdepth ...
- else
- texset("prevdepth",ignoredepth)
- outer.prevdepth = ignoredepth
- end
- texset("prevgraf", newlines)
- outer.prevgraf = newlines
+ return noflines
+ end
+ end
+
+ interfaces.implement {
+ name = "getnofpreviouslines",
+ public = true,
+ actions = vspacing.getnofpreviouslines,
+ }
+
+ function vspacing.synchronizepage()
+ if enabled then
if trace then
- report("page %i, prevdepth %p (last depth %p), prevgraf %i (from %i), %sboxes",
- texgetcount("realpageno"),olddepth,newdepth,oldlines,newlines,boxfound and "" or "no ")
+ local newdepth = outer.prevdepth
+ local olddepth = newdepth
+ if not texlists.page_head then
+ newdepth = ignoredepth
+ texset("prevdepth",ignoredepth)
+ outer.prevdepth = ignoredepth
+ end
+ report("page %i, prevdepth %p => %p",texgetcount("realpageno"),olddepth,newdepth)
+ -- report("list %s",nodes.idsandsubtypes(head))
+ else
+ if not texlists.page_head then
+ texset("prevdepth",ignoredepth)
+ outer.prevdepth = ignoredepth
+ end
end
end
end
@@ -2226,7 +2261,7 @@ do
-- end
-- }
- interfaces.implement {
+ implement {
name = "removelastline",
actions = function()
local head = texlists.page_head
@@ -2242,7 +2277,7 @@ do
end
}
- interfaces.implement {
+ implement {
name = "showpagelist", -- will improve
actions = function()
local head = texlists.page_head
@@ -2256,4 +2291,14 @@ do
end
}
+ implement {
+ name = "pageoverflow",
+ actions = { vspacing.pageoverflow, context }
+ }
+
+ implement {
+ name = "forcepageflush",
+ actions = vspacing.forcepageflush
+ }
+
end
diff --git a/tex/context/base/mkiv/spac-ver.mkiv b/tex/context/base/mkiv/spac-ver.mkiv
index b71e28219..7b36f9a5b 100644
--- a/tex/context/base/mkiv/spac-ver.mkiv
+++ b/tex/context/base/mkiv/spac-ver.mkiv
@@ -15,7 +15,7 @@
\unprotect
-\registerctxluafile{spac-ver}{}
+\registerctxluafile{spac-ver}{optimize}
% todo: use usernodes ?
@@ -165,6 +165,8 @@
\installcommandhandler \??interlinespace {interlinespace} \??interlinespace
+\installmacrostack\currentinterlinespace
+
\unexpanded\def\setupinterlinespace
{\dodoubleempty\spac_linespacing_setup}
@@ -205,7 +207,7 @@
\ifx\p_spac_checked_interlinespace\empty
\spac_linespacing_synchronize_local
\else\ifcsname\namedinterlinespacehash\p_spac_checked_interlinespace\s!parent\endcsname % we could have a \s!check
- \pushmacro\currentinterlinespace
+ \push_macro_currentinterlinespace
\let\currentinterlinespace\p_spac_checked_interlinespace
\spac_linespacing_setup_specified_interline_space % \dosetupspecifiedinterlinespaceindeed
\iflocalinterlinespace
@@ -215,7 +217,7 @@
\the\everysetuplocalinterlinespace
\localinterlinespacefalse
\fi
- \popmacro\currentinterlinespace
+ \pop_macro_currentinterlinespace
\else
\normalexpanded{\noexpand\doifelseassignment{\p_spac_checked_interlinespace}%
\setupspecifiedinterlinespace\setuprelativeinterlinespace[\p_spac_checked_interlinespace]}%
@@ -230,9 +232,9 @@
\unexpanded\def\setuplocalinterlinespace[#1]%
{\localinterlinespacetrue
- \pushmacro\currentinterlinespace
+ \push_macro_currentinterlinespace
\setupinterlinespace[#1]%
- \popmacro\currentinterlinespace
+ \pop_macro_currentinterlinespace
\localinterlinespacefalse}
\let\switchtointerlinespace\setuplocalinterlinespace
@@ -282,47 +284,50 @@
\unexpanded\def\smallbreak
{\par
- \ifdim\lastskip<\smallskipamount
+ \ifvmode\ifdim\lastskip<\smallskipamount
\removelastskip
- \penalty-50
+ \penalty-\plusfifty
\smallskip
- \fi}
+ \fi\fi}
\unexpanded\def\medbreak
{\par
- \ifdim\lastskip<\medskipamount
+ \ifvmode\ifdim\lastskip<\medskipamount
\removelastskip
- \penalty-100
+ \penalty-\plusonehundred
\medskip
- \fi}
+ \fi\fi}
\unexpanded\def\bigbreak
{\par
- \ifdim\lastskip<\bigskipamount
+ \ifvmode\ifdim\lastskip<\bigskipamount
\removelastskip
- \penalty-200
+ \penalty-\plustwohundred
\bigskip
- \fi}
+ \fi\fi}
-\unexpanded\def\break {\penalty-\plustenthousand} % can be hmode or vmode
-\unexpanded\def\nobreak {\penalty \plustenthousand} % can be hmode or vmode
-\unexpanded\def\allowbreak{\penalty \zeropoint} % can be hmode or vmode
-\unexpanded\def\goodbreak {\par\penalty-500\relax} % forces vmode
-\unexpanded\def\filbreak {\par\vfil\penalty-200\vfilneg} % forces vmode
+\unexpanded\def\break {\penalty-\plustenthousand} % can be hmode or vmode
+\unexpanded\def\nobreak {\penalty \plustenthousand} % can be hmode or vmode
+\unexpanded\def\allowbreak{\penalty \zerocount} % can be hmode or vmode
+
+\unexpanded\def\goodbreak {\par\ifvmode\penalty-\plusfivehundred\relax\fi} % forces vmode
+\unexpanded\def\filbreak {\par\ifvmode\vfil\penalty-\plustwohundred\vfilneg\fi} % forces vmode
%D Made slightly more readable:
\unexpanded\def\vglue {\afterassignment\spac_helpers_vglue_indeed\s_spac_lastskip=}
\unexpanded\def\hglue {\afterassignment\spac_helpers_hglue_indeed\s_spac_lastskip=}
-\unexpanded\def\topglue{\nointerlineskip\vglue-\topskip\vglue}
+\unexpanded\def\topglue{\par\ifvmode\nointerlineskip\vglue-\topskip\vglue\fi}
\def\spac_helpers_vglue_indeed
{\par
- \d_spac_prevdepth\prevdepth
- \hrule\s!height\zeropoint
- \nobreak
- \vskip\s_spac_lastskip
- \prevdepth\d_spac_prevdepth}
+ \ifvmode
+ \d_spac_prevdepth\prevdepth
+ \hrule\s!height\zeropoint
+ \nobreak
+ \vskip\s_spac_lastskip
+ \prevdepth\d_spac_prevdepth
+ \fi}
\def\spac_helpers_hglue_indeed
{\dontleavehmode
@@ -895,11 +900,14 @@
\dosetstrut}
\unexpanded\def\setcharstrut#1%
- {\setbox\strutbox\hbox{#1}% hm, maybe hpack i.e. why apply fonts .. conceptual choice
+ {\setbox\strutbox\hbox{#1}% no \hpack, in case we have smallcaps
\strutht\ht\strutbox
\strutdp\dp\strutbox
\dosetstrut}
+\unexpanded\def\settightstrut
+ {\setcharstrut{(}}
+
\unexpanded\def\setfontstrut
{\setcharstrut{(gplQT}}
@@ -1307,9 +1315,41 @@
\let\normaloffinterlineskip\offinterlineskip % knuth's original
+%D This is tricky. The prevdepth value is still set to the last one even if there is
+%D nothing on the page. The same is true for prevgraf, which doesn't resemble the
+%D value on the current page.
+%D
+%D So, here we kick in a checker but it has to happen after the output group and it
+%D only has to be done once (output can trigger itself!).
+%D
+%D However, prevgraf is somehow bound to hangindent so we can get very
+%D nasty side effects. So, in tne end we use our own variable!
+
+\ifdefined\getnofpreviouslines
+ % defined public at the lua end
+\else
+ \let\getnofpreviouslines\!!zerocount
+\fi
+
+\unexpanded\def\page_otr_synchronize_page_yes
+ {\aftergroup\page_otr_synchronize_page_indeed
+ \glet\page_otr_synchronize_page\relax}
+
+% \unexpanded\def\page_otr_synchronize_page_indeed
+% {\clf_synchronizepage
+% \glet\page_otr_synchronize_page\page_otr_synchronize_page_yes}
+%
+% This has to become an otr method: \s!page_otr_command_synchonize_page
+
+\unexpanded\def\page_otr_synchronize_page_indeed
+ {\ifx\currentoutputroutine\s!multicolumn\else\clf_synchronizepage\fi
+ \glet\page_otr_synchronize_page\page_otr_synchronize_page_yes}
+
+\let\page_otr_synchronize_page\page_otr_synchronize_page_yes
+
\appendtoks
- \ifvmode\clf_synchronizepage\fi % a nasty hack (tested for a while now)
-\to \everyafteroutput
+ \page_otr_synchronize_page
+\to \everyaftershipout
%D My own one:
@@ -1361,7 +1401,7 @@
\let\restoreinterlinepenalty\relax
\unexpanded\def\spac_penalties_restore
- {\global\let\restoreinterlinepenalty\relax
+ {\glet\restoreinterlinepenalty\relax
\global\resetpenalties\interlinepenalties
\global\c_spac_keep_lines_together\zerocount}
@@ -1369,7 +1409,7 @@
{\ifnum#1>\c_spac_keep_lines_together
\global\c_spac_keep_lines_together#1%
\global\setpenalties\interlinepenalties\c_spac_keep_lines_together\plustenthousand
- \global\let\restoreinterlinepenalty\spac_penalties_restore
+ \glet\restoreinterlinepenalty\spac_penalties_restore
\fi}
\def\defaultdisplaywidowpenalty {50}
@@ -1701,7 +1741,7 @@
\fi
\doifelsenothing{#1}{\spac_grids_snap_value_set\v!normal}{\spac_grids_snap_value_set{#1}}%
\clf_vspacingsnap\nextbox\attribute\snapmethodattribute\relax
- \ifvbox\nextbox\vbox\else\hbox\fi attr \snapmethodattribute \zerocount {\box\nextbox}% *pack ?
+ \ifvbox\nextbox\vbox\else\hbox\fi attr \snapmethodattribute \zerocount {\box\nextbox}% no pack (?), we snap
\egroup}
\def\spac_grids_check_nop
@@ -1816,15 +1856,15 @@
\unexpanded\def\gridboxvbox
{\ifcase\gridboxlinemode
- \vbox
+ \vpack
\or
- \ruledvbox
+ \ruledvpack
\or
- \vbox
+ \vpack
\or
- \ruledvbox
+ \ruledvpack
\else
- \ruledvbox
+ \ruledvpack
\fi}
\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth}
@@ -1836,8 +1876,10 @@
\resetteststrut
\offinterlineskip
\hsize#2%
- \ifnum\gridboxlinenomode=\plusthree
- \gridboxlinenomode\ifodd\realpageno\plusone\else\plustwo\fi
+ \ifcase\gridboxlinenomode\or\or\or
+ \gridboxlinenomode\doifoddpageelse\plusone\plustwo % 3: outer
+ \or
+ \gridboxlinenomode\doifoddpageelse\plustwo\plusone % 4: inner
\fi
\topskipcorrection
\gridboxvbox % calculated size
@@ -2014,7 +2056,7 @@
\expandafter\nostartblankhandling
\fi}
-\def\nostartblankhandling#1\stopblankhandling
+\unexpanded\def\nostartblankhandling#1\stopblankhandling
{}
\def\dostartblankhandling
@@ -2042,7 +2084,7 @@
\setfalse\c_space_vspacing_done
\the\everybeforeblankhandling}
-\def\addpredefinedblankskip#1#2%
+\unexpanded\def\addpredefinedblankskip#1#2%
{\settrue\c_space_vspacing_done
\advance\s_spac_vspacing_temp#1\dimexpr\csname\??vspacingamount#2\endcsname\relax}
@@ -2089,8 +2131,56 @@
\def\spac_vspacing_nop_ignore
{\ifmmode\else\par\fi}
-\def\directvspacing#1%
- {\par\clf_vspacing{#1}}
+% \unexpanded\def\directvspacing#1%
+% {\par\clf_vspacing{#1}}
+%
+%
+% \def\directdefaultvspacing
+% {\ifinpagebody % somewhat weird
+% \clf_vspacing{\currentvspacing}%
+% \else\ifconditional\c_spac_packed_blank
+% \clf_vspacing{\currentvspacing}%
+% \fi\fi}
+%
+% \unexpanded\def\useblankparameter#1% faster local variant
+% {\edef\m_spac_blank_asked{#1\c!blank}%
+% \ifx\m_spac_blank_asked\empty\else
+% \clf_vspacing{\m_spac_blank_asked}
+% \fi}
+
+\installcorenamespace{vspacing}
+
+\unexpanded\def\directvspacing#1%
+ {\par
+ \ifcsname\??vspacing#1\endcsname
+ \lastnamedcs
+ \else
+ \spac_vspacing_yes_preset{#1}%
+ \fi}
+
+\def\spac_vspacing_yes_preset#1%
+ {\setxvalue{\??vspacing#1}{\clf_vspacing{#1}}%
+ %\writestatus{}{}%
+ %\writestatus{#1}{\expandafter\meaning\csname\??vspacing#1\endcsname}%
+ %\writestatus{}{}%
+ \csname\??vspacing#1\endcsname}
+
+\def\spac_vspacing_yes_indeed[#1]%
+ {\ifmmode\else
+ \directvspacing{#1}%
+ \fi}
+
+\def\spac_vspacing_nop_indeed
+ {\ifmmode\else
+ \directvspacing\currentvspacing
+ \fi}
+
+\def\directdefaultvspacing
+ {\ifinpagebody % somewhat weird
+ \directvspacing\currentvspacing
+ \else\ifconditional\c_spac_packed_blank
+ \directvspacing\currentvspacing
+ \fi\fi}
\def\directcheckedvspacing
{\ifinpagebody % somewhat weird
@@ -2101,17 +2191,10 @@
\doubleexpandafter\gobbleoneargument
\fi\fi}
-\def\directdefaultvspacing
- {\ifinpagebody % somewhat weird
- \clf_vspacing{\currentvspacing}%
- \else\ifconditional\c_spac_packed_blank
- \clf_vspacing{\currentvspacing}%
- \fi\fi}
-
\unexpanded\def\useblankparameter#1% faster local variant
{\edef\m_spac_blank_asked{#1\c!blank}%
\ifx\m_spac_blank_asked\empty\else
- \clf_vspacing{\m_spac_blank_asked}
+ \directvspacing\m_spac_blank_asked
\fi}
% handy (and faster):
@@ -2418,13 +2501,14 @@
\scratchwidth\dimexpr\wd\nextbox+\scratchdistance\relax
\ifx\m_spac_hanging_location\v!right
\hangindent\ifconditional\displaylefttoright-\fi\scratchwidth
- \rlap{\hskip\dimexpr\hsize-\wd\nextbox\relax\box\nextbox}%
+ \rlap{\hskip\dimexpr\hsize-\leftskip-\wd\nextbox\relax\box\nextbox}% \leftskip is new
\else
\hangindent\ifconditional\displaylefttoright\else-\fi\scratchwidth
\llap{\box\nextbox\hskip\scratchdistance}%
\fi
\ignorespaces}
+
%D \macros
%D {startfixed}
%D
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index 74e8e3e8a..49b023fb8 100644
--- a/tex/context/base/mkiv/status-files.pdf
+++ b/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index a2f2ee28b..8cbd7014c 100644
--- a/tex/context/base/mkiv/status-lua.pdf
+++ b/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/strc-blk.lua b/tex/context/base/mkiv/strc-blk.lua
index 703d36379..89df440c9 100644
--- a/tex/context/base/mkiv/strc-blk.lua
+++ b/tex/context/base/mkiv/strc-blk.lua
@@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['strc-blk'] = {
-- this one runs on top of buffers and structure
local type, next = type, next
-local find, format, validstring = string.find, string.format, string.valid
+local find, formatters, validstring = string.find, string.formatters, string.valid
local settings_to_set, settings_to_array = utilities.parsers.settings_to_set, utilities.parsers.settings_to_array
local allocate = utilities.storage.allocate
@@ -25,6 +25,7 @@ structures.blocks = structures.blocks or { }
local blocks = structures.blocks
local sections = structures.sections
local lists = structures.lists
+local helpers = structures.helpers
local collected = allocate()
local tobesaved = allocate()
@@ -42,14 +43,28 @@ end
job.register('structures.blocks.collected', tobesaved, initializer)
local listitem = utilities.parsers.listitem
+local f_block = formatters["block.%s"]
+
+function blocks.uservariable(index,key,default)
+ local c = collected[index]
+ if c then
+ local u = c.userdata
+ if u then
+ local v = u[key] or default
+ if v then
+ context(v)
+ end
+ end
+ end
+end
-function blocks.print(name,data,hide)
+local function printblock(index,name,data,hide)
if hide then
- context.dostarthiddenblock(name)
+ context.dostarthiddenblock(index,name)
else
- context.dostartnormalblock(name)
+ context.dostartnormalblock(index,name)
end
- context.viafile(data,format("block.%s",validstring(name,"noname")))
+ context.viafile(data,f_block(validstring(name,"noname")))
if hide then
context.dostophiddenblock()
else
@@ -57,12 +72,14 @@ function blocks.print(name,data,hide)
end
end
+blocks.print = printblock
+
function blocks.define(name)
states[name] = { all = "hide" }
end
function blocks.setstate(state,name,tag)
- local all = tag == ""
+ local all = tag == ""
local tags = not all and settings_to_array(tag)
for n in listitem(name) do
local sn = states[n]
@@ -98,12 +115,12 @@ function blocks.select(state,name,tag,criterium)
local metadata = ri.metadata
if names[metadata.name] then
if all then
- blocks.print(name,ri.data,hide)
+ printblock(ri.index,name,ri.data,hide)
else
local mtags = metadata.tags
for tag, sta in next, tags do
if mtags[tag] then
- blocks.print(name,ri.data,hide)
+ printblock(ri.index,name,ri.data,hide)
break
end
end
@@ -112,41 +129,51 @@ function blocks.select(state,name,tag,criterium)
end
end
-function blocks.save(name,tag,buffer) -- wrong, not yet adapted
- local data = buffers.getcontent(buffer)
- local tags = settings_to_set(tag)
- local plus, minus = false, false
- if tags['+'] then plus = true tags['+'] = nil end
- if tags['-'] then minus = true tags['-'] = nil end
- tobesaved[#tobesaved+1] = {
- metadata = {
- name = name,
- tags = tags,
- plus = plus,
+function blocks.save(name,tag,userdata,buffer) -- wrong, not yet adapted
+ local data = buffers.getcontent(buffer)
+ local tags = settings_to_set(tag)
+ local plus = false
+ local minus = false
+ local last = #tobesaved + 1
+ local all = states[name].all
+ if tags['+'] then
+ plus = true
+ tags['+'] = nil
+ end
+ if tags['-'] then
+ minus = true
+ tags['-'] = nil
+ end
+ tobesaved[last] = helpers.simplify {
+ metadata = {
+ name = name,
+ tags = tags,
+ plus = plus,
minus = minus,
},
+ index = last,
+ data = data or "error",
+ userdata = userdata and type(userdata) == "string" and helpers.touserdata(userdata),
references = {
- section = sections.currentid(),
+ section = sections.currentid(),
},
- data = data or "error",
}
- local allstate = states[name].all
if not next(tags) then
- if allstate ~= "hide" then
- blocks.print(name,data)
+ if all ~= "hide" then
+ printblock(last,name,data)
elseif plus then
- blocks.print(name,data,true)
+ printblock(last,name,data,true)
end
else
local sn = states[name]
for tag, _ in next, tags do
if sn[tag] == nil then
- if allstate ~= "hide" then
- blocks.print(name,data)
+ if all ~= "hide" then
+ printblock(last,name,data)
break
end
elseif sn[tag] ~= "hide" then
- blocks.print(name,data)
+ printblock(last,name,data)
break
end
end
@@ -156,7 +183,8 @@ end
-- interface
-implement { name = "definestructureblock", actions = blocks.define, arguments = "string" }
-implement { name = "savestructureblock", actions = blocks.save, arguments = "3 strings" }
-implement { name = "selectstructureblock", actions = blocks.select, arguments = "4 strings" }
-implement { name = "setstructureblockstate", actions = blocks.setstate, arguments = "3 strings" }
+implement { name = "definestructureblock", actions = blocks.define, arguments = "string" }
+implement { name = "savestructureblock", actions = blocks.save, arguments = "4 strings" }
+implement { name = "selectstructureblock", actions = blocks.select, arguments = "4 strings" }
+implement { name = "setstructureblockstate", actions = blocks.setstate, arguments = "3 strings" }
+implement { name = "structureblockuservariable", actions = blocks.uservariable, arguments = { "integer", "string" } }
diff --git a/tex/context/base/mkiv/strc-blk.mkiv b/tex/context/base/mkiv/strc-blk.mkiv
index c42bb25ec..e52198721 100644
--- a/tex/context/base/mkiv/strc-blk.mkiv
+++ b/tex/context/base/mkiv/strc-blk.mkiv
@@ -34,48 +34,125 @@
\appendtoks
\clf_definestructureblock{\currentblock}%
- \setuevalue{\e!begin\currentblock}{\dodoubleempty\strc_blocks_begin[\currentblock]}%
- \setuevalue{\e!end \currentblock}{}%
+ \setuevalue{\e!begin\currentblock}{\strc_blocks_begin{\currentblock}}%
+ \letvalue {\e!end \currentblock}\donothing
\to \everydefineblock
-\unexpanded\def\strc_blocks_begin[#1][#2]%
- {\normalexpanded{\buff_pickup{@block@}{\e!begin#1}{\e!end#1}}
- {}% before
- {\clf_savestructureblock{#1}{#2}{@block@}}%
- \plusone}% after
+% The naive way:
+%
+% \unexpanded\def\strc_blocks_begin#1%
+% {\dotripleempty\strc_blocks_begin_indeed[#1]}
+%
+% \unexpanded\def\strc_blocks_begin_indeed[#1][#2][#3]%
+% {\normalexpanded{\buff_pickup{\??block}{\e!begin#1}{\e!end#1}}
+% {}%
+% {\clf_savestructureblock{#1}{#2}{#3}{\??block}}%
+% \plusone}%
+%
+% We need to prevent too much lookahead which will gobble newlines
+% that are needed for buffers. See blocks-002.tex as example.
+
+% maybe: systemmode "block:<name>"
+
+\let\m_block \empty
+\let\m_subblock\empty
+
+\unexpanded\def\strc_blocks_begin#1%
+ {\edef\m_block {#1}%
+ \let \m_subblock\empty
+ \doifelsenextoptionalcs\strc_blocks_begin_yes\strc_blocks_begin_nop}
+
+\unexpanded\def\strc_blocks_begin_yes[#1]%
+ {\doifelseassignmentcs{#1}%
+ \strc_blocks_begin_indeed
+ \strc_blocks_begin_tagged
+ {#1}}
+
+\unexpanded\def\strc_blocks_begin_tagged#1%
+ {\edef\m_subblock{#1}%
+ \doifelsenextoptionalcs\strc_blocks_begin_yes_yes\strc_blocks_begin_nop}
+
+\unexpanded\def\strc_blocks_begin_yes_yes[#1]%
+ {\strc_blocks_begin_indeed{#1}}
+
+\unexpanded\def\strc_blocks_begin_nop
+ {\strc_blocks_begin_indeed{}}
+
+\unexpanded\def\strc_blocks_begin_indeed#1%
+ {\normalexpanded{\buff_pickup{\??block}{\e!begin\m_block}{\e!end\m_block}}%
+ {}%
+ {\clf_savestructureblock{\m_block}{\m_subblock}{#1}{\??block}}%
+ \plusone}
\let\strc_blocks_setup\relax
+\newconstant \c_strc_blocks_index
+\newconditional\c_strc_blocks_display
+
\unexpanded\def\dostarthiddenblock % called at lua end
- {\startnointerference
- \dostartnormalblock}
+ {\begingroup
+ \visiblefalse % blocks float
+ \startnointerference
+ \strc_start_block}
\unexpanded\def\dostophiddenblock % called at lua end
- {\dostopnormalblock
- \stopnointerference}
+ {\strc_stop_block
+ \stopnointerference
+ \endgroup}
+
+\unexpanded\def\dostartnormalblock % called at lua end
+ {\begingroup
+ \visibletrue
+ \strc_start_block}
-\unexpanded\def\dostartnormalblock#1% called at lua end
- {\bgroup
- \visibletrue % will change
- \edef\currentblock{#1}%
+\unexpanded\def\dostopnormalblock % called at lua end
+ {\strc_stop_block
+ \endgroup}
+
+\def\strc_start_block#1#2%
+ {\edef\currentblock{#2}%
+ \c_strc_blocks_index#1\relax
\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
+ \edef\p_alternative{\blockparameter\c!alternative}%
+ \ifx\p_alternative\v!text
+ \setfalse\c_strc_blocks_display
+ \else
+ \settrue\c_strc_blocks_display
+ \fi
+ \ifconditional\c_strc_blocks_display
+ \blockparameter\c!before
+ \fi
+ \begingroup
+ \usesetupsparameter\blockparameter\relax
+ \dostarttagged\t!block\currentblock
+ \useblockstyleandcolor\c!style\c!color
+ \blockparameter\c!inner % old
+ \ifconditional\c_strc_blocks_display
+ \usealignparameter\blockparameter
+ \else
+ \blockparameter\c!left
+ \fi
\ignorespaces}
-\unexpanded\def\dostopnormalblock % called at lua end
+\def\strc_stop_block
{\removeunwantedspaces
- \blockparameter\c!after
- \par % todo: alternative = text, paragraph
- \egroup}
+ \ifconditional\c_strc_blocks_display
+ \par
+ \else
+ \blockparameter\c!right
+ \fi
+ \dostoptagged
+ \endgroup
+ \ifconditional\c_strc_blocks_display
+ \blockparameter\c!after
+ \fi}
\def\strc_blocks_set_state[#1][#2][#3]% state name tag
{\clf_setstructureblockstate{#1}{#2}{#3}}
\def\strc_blocks_select[#1][#2][#3][#4]% state name tag setups
- {\bgroup
+ {\begingroup
\doifelseassignment{#3}
{\getparameters[\??blocktemp][\c!criterium=\v!text,#3]%
\def\strc_blocks_setup{\setupcurrentblock[#3]}%
@@ -83,7 +160,10 @@
{\getparameters[\??blocktemp][\c!criterium=\v!text,#4]%
\def\strc_blocks_setup{\setupcurrentblock[#4]}%
\clf_selectstructureblock{#1}{#2}{#3}{\csname\??blocktemp\c!criterium\endcsname}}%
- \egroup}
+ \endgroup}
+
+\def\blockuservariable#1%
+ {\clf_structureblockuservariable\c_strc_blocks_index{#1}}
% hide : save, if [+] also hidden execute
% keep : save and normal execute
diff --git a/tex/context/base/mkiv/strc-con.mkvi b/tex/context/base/mkiv/strc-con.mkvi
index 57b69cc7f..d67307ba7 100644
--- a/tex/context/base/mkiv/strc-con.mkvi
+++ b/tex/context/base/mkiv/strc-con.mkvi
@@ -980,11 +980,11 @@
\xdef\currentconstructionincrementnumber{\constructionparameter\c!incrementnumber}%
%
\ifx\currentconstructionexpansion\empty
- \global\let\currentconstructionexpansion\v!no
+ \glet\currentconstructionexpansion\v!no
\fi
%
\ifx\currentconstructionreferenceprefix\empty
- \global\let\currentconstructionreferenceprefix\referenceprefix
+ \glet\currentconstructionreferenceprefix\referenceprefix
\fi
\ifx\currentconstructionexpansion\s!xml
\xmlstartraw
@@ -994,9 +994,9 @@
\xdef\currentconstructionlist {\constructionparameter\c!list}%
\xmlstopraw
\ifx\currentconstructionlist\empty
- \global\let\currentconstructionlist\currentconstructiontitle
+ \glet\currentconstructionlist\currentconstructiontitle
\fi
- \global\let\currentconstructioncoding\s!xml
+ \glet\currentconstructioncoding\s!xml
\else
\ifx\currentconstructionexpansion\v!yes
\xdef\currentconstructiontitle {\constructionparameter\c!title}%
@@ -1016,9 +1016,9 @@
\fi \fi
\fi
\ifx\currentconstructionlist\empty
- \globallet\currentconstructionlist\currentconstructiontitle
+ \glet\currentconstructionlist\currentconstructiontitle
\fi
- \globallet\currentconstructioncoding\s!tex
+ \glet\currentconstructioncoding\s!tex
\fi
%
\ifx\currentconstructiontitle\v!none % will become obsolete
@@ -1093,7 +1093,7 @@
\endgroup
\edef\noexpand\currentconstructionlistentry {\the\scratchcounter}%
\edef\noexpand\currentconstructionattribute {\the\lastdestinationattribute}%
- \edef\noexpand\currentconstructionsynchronize{\ctxlatecommand{enhancelist(\the\scratchcounter)}}%
+ \edef\noexpand\currentconstructionsynchronize{\clf_deferredenhancelist\the\scratchcounter}%
}%
\fi}
@@ -1103,11 +1103,11 @@
\def\reinstateconstructionnumberentry#1% was xdef
{\edef\currentconstructionattribute {\clf_getinternallistreference#1}%
- \edef\currentconstructionsynchronize{\ctxlatecommand{enhancelist(#1)}}}
+ \edef\currentconstructionsynchronize{\clf_deferredenhancelist\number#1}}
\def\reinstatecachedconstructionnumberentry#1% was xdef | #1 = cached index can be different from real
{\edef\currentconstructionattribute {\clf_getinternalcachedlistreference#1}% destination
- \edef\currentconstructionsynchronize{\ctxlatecommand{enhancelist(#1)}}}
+ \edef\currentconstructionsynchronize{\clf_deferredenhancelist\number#1}}
\installstructurelistprocessor{construction}{\usestructurelistprocessor{number+title}}
diff --git a/tex/context/base/mkiv/strc-def.mkiv b/tex/context/base/mkiv/strc-def.mkiv
index 8d1fa371f..941f561c8 100644
--- a/tex/context/base/mkiv/strc-def.mkiv
+++ b/tex/context/base/mkiv/strc-def.mkiv
@@ -65,6 +65,17 @@
\setsectionblock [\v!bodypart] % default
+% \setuphead[sectionsegments=\currentheadlevel]
+% \setuphead[sectionsegments=current]
+%
+% \startchapter[title=One,ownnumber={A}]
+% \startsection[title=OneOne,ownnumber={A.B}]
+% \startsubsection[title=OneOneOne,ownnumber={A.B.C}]
+% test
+% \stopsubsection
+% \stopsection
+% \stopchapter
+
% \appendtoks
% \setsectionblock[\v!bodypart]% default
% \to \everyjob
diff --git a/tex/context/base/mkiv/strc-doc.lua b/tex/context/base/mkiv/strc-doc.lua
index 2de26ac64..4b2ac04b7 100644
--- a/tex/context/base/mkiv/strc-doc.lua
+++ b/tex/context/base/mkiv/strc-doc.lua
@@ -18,6 +18,7 @@ if not modules then modules = { } end modules ['strc-doc'] = {
local next, type, tonumber, select = next, type, tonumber, select
local find, match = string.find, string.match
local concat, fastcopy, insert, remove = table.concat, table.fastcopy, table.insert, table.remove
+local sortedhash, sortedkeys = table.sortedhash, table.sortedkeys
local max, min = math.max, math.min
local allocate, mark, accesstable = utilities.storage.allocate, utilities.storage.mark, utilities.tables.accesstable
local setmetatableindex = table.setmetatableindex
@@ -37,11 +38,13 @@ local v_auto = variables.auto
local v_strict = variables.strict
local v_all = variables.all
local v_positive = variables.positive
+local v_current = variables.current
local trace_sectioning = false trackers.register("structures.sectioning", function(v) trace_sectioning = v end)
local trace_detail = false trackers.register("structures.detail", function(v) trace_detail = v end)
local report_structure = logs.reporter("structure","sectioning")
+local report_used = logs.reporter("structure")
local context = context
local commands = commands
@@ -122,12 +125,16 @@ local tobesaved = allocate()
sections.collected = collected
sections.tobesaved = tobesaved
--- local function initializer()
--- collected = sections.collected
--- tobesaved = sections.tobesaved
--- end
---
--- job.register('structures.sections.collected', tobesaved, initializer)
+-- We have to save this mostly redundant list because we can have (rare)
+-- cases with own numbers that don't end up in the list so we get out of
+-- sync when we use (*).
+
+local function initializer()
+ collected = sections.collected
+ tobesaved = sections.tobesaved
+end
+
+job.register('structures.sections.collected', tobesaved, initializer)
local registered = sections.registered or allocate()
sections.registered = registered
@@ -158,7 +165,7 @@ end
local lastsaved = 0
function sections.save(sectiondata)
--- local sectionnumber = helpers.simplify(section.sectiondata) -- maybe done earlier
+local sectiondata = helpers.simplify(sectiondata) -- maybe done earlier
local numberdata = sectiondata.numberdata
local ntobesaved = #tobesaved
if not numberdata or sectiondata.metadata.nolist then
@@ -178,28 +185,28 @@ function sections.currentsectionindex()
return lastsaved -- only for special controlled situations
end
-function sections.load()
- setmetatableindex(collected,nil)
- local lists = lists.collected
- for i=1,#lists do
- local list = lists[i]
- local metadata = list.metadata
- if metadata and metadata.kind == "section" and not metadata.nolist then
- local numberdata = list.numberdata
- if numberdata then
- collected[#collected+1] = numberdata
- end
- end
- end
- sections.load = functions.dummy
-end
-
-table.setmetatableindex(collected, function(t,i)
- sections.load()
- return collected[i] or { }
-end)
-
+-- See comment above (*). We cannot use the following space optimization:
+--
+-- function sections.load()
+-- setmetatableindex(collected,nil)
+-- local lists = lists.collected
+-- for i=1,#lists do
+-- local list = lists[i]
+-- local metadata = list.metadata
+-- if metadata and metadata.kind == "section" and not metadata.nolist then
+-- local numberdata = list.numberdata
+-- if numberdata then
+-- collected[#collected+1] = numberdata
+-- end
+-- end
+-- end
+-- sections.load = functions.dummy
+-- end
--
+-- table.setmetatableindex(collected, function(t,i)
+-- sections.load()
+-- return collected[i] or { }
+-- end)
sections.verbose = true
@@ -382,8 +389,9 @@ function sections.setentry(given)
-- new number
olddepth = newdepth
if metadata.increment then
- local oldn, newn = numbers[newdepth] or 0, 0
- local fd = forced[newdepth]
+ local oldn = numbers[newdepth] or 0
+ local newn = 0
+ local fd = forced[newdepth]
if fd then
if fd[1] == "add" then
newn = oldn + fd[2] + 1
@@ -438,7 +446,10 @@ end
function sections.reportstructure()
if sections.verbose then
- local numbers, ownnumbers, status, depth = data.numbers, data.ownnumbers, data.status, data.depth
+ local numbers = data.numbers
+ local ownnumbers = data.ownnumbers
+ local status = data.status
+ local depth = data.depth
local d = status[depth]
local o = concat(ownnumbers,".",1,depth)
local n = (numbers and concat(numbers,".",1,min(depth,#numbers))) or 0
@@ -711,8 +722,12 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
criterium = 0
end
--
- local firstprefix, lastprefix = 0, 16 -- too much, could max found level
- if segments then
+ local firstprefix = 0
+ local lastprefix = 16 -- too much, could max found level
+ if segments == v_current then
+ firstprefix = data.depth
+ lastprefix = firstprefix
+ elseif segments then
local f, l = match(tostring(segments),"^(.-):(.+)$")
if l == "*" or l == v_all then
l = 100 -- new
@@ -731,9 +746,11 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
end
end
--
- local numbers, ownnumbers = entry.numbers, entry.ownnumbers
+ local numbers = entry.numbers
+ local ownnumbers = entry.ownnumbers
if numbers then
- local done, preceding = false, false
+ local done = false
+ local preceding = false
--
local result = kind == "direct" and { }
if result then
@@ -751,11 +768,14 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
if prefixlist and (kind == "section" or kind == "prefix" or kind == "direct") then
-- find valid set (problem: for sectionnumber we should pass the level)
-- no holes
- local b, e, bb, ee = 1, #prefixlist, 0, 0
+ local b = 1
+ local e = #prefixlist
+ local bb = 0
+ local ee = 0
-- find last valid number
for k=e,b,-1 do
local prefix = prefixlist[k]
- local index = sections.getlevel(prefix) or k
+ local index = sections.getlevel(prefix) or k
if index >= firstprefix and index <= lastprefix then
local number = numbers and numbers[index]
if number then
@@ -771,7 +791,7 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
-- find valid range
for k=b,e do
local prefix = prefixlist[k]
- local index = sections.getlevel(prefix) or k
+ local index = sections.getlevel(prefix) or k
if index >= firstprefix and index <= lastprefix then
local number = numbers and numbers[index]
if number then
@@ -972,6 +992,47 @@ function sections.getnumber(depth,what) -- redefined here
context(askednumber)
end
+-- maybe handy
+
+function sections.showstructure()
+
+ local tobesaved = structures.lists.tobesaved
+
+ if not tobesaved then
+ return
+ end
+
+ local levels = setmetatableindex("table")
+ local names = setmetatableindex("table")
+
+ report_used()
+ report_used("sections")
+ for i=1,#tobesaved do
+ local si = tobesaved[i]
+ local md = si.metadata
+ if md and md.kind == "section" then
+ local level = md.level
+ local name = md.name
+ local numbers = si.numberdata.numbers
+ local title = si.titledata.title
+ report_used(" %i : %-10s %-20s %s",level,concat(numbers,"."),name,title)
+ levels[level][name] = true
+ names[name][level] = true
+ end
+ end
+ report_used()
+ report_used("levels")
+ for level, list in sortedhash(levels) do
+ report_used(" %s : % t",level,sortedkeys(list))
+ end
+ report_used()
+ report_used("names")
+ for name, list in sortedhash(names) do
+ report_used(" %-10s : % t",name,sortedkeys(list))
+ end
+ report_used()
+end
+
-- experimental
local levels = { }
@@ -1042,6 +1103,7 @@ implement { name = "getsomefullstructurenumber", actions = sections.fullnumber,
implement { name = "getspecificstructuretitle", actions = sections.structuredata, arguments = { "string", "'titledata.title'",false,"string" } }
implement { name = "reportstructure", actions = sections.reportstructure }
+implement { name = "showstructure", actions = sections.showstructure }
implement {
name = "registersection",
diff --git a/tex/context/base/mkiv/strc-doc.mkiv b/tex/context/base/mkiv/strc-doc.mkiv
index 805525487..516d87efe 100644
--- a/tex/context/base/mkiv/strc-doc.mkiv
+++ b/tex/context/base/mkiv/strc-doc.mkiv
@@ -19,6 +19,16 @@
%D This will move:
+% \unexpanded\def\setstructuresynchronization#1% todo: use ctxcontext
+% {\clf_setinternalreference
+% prefix {\currentstructurereferenceprefix}%
+% reference {\currentstructurereference}
+% internal \locationcount
+% view {\interactionparameter\c!focus}%
+% \relax
+% \xdef\currentstructureattribute {\the\lastdestinationattribute}%
+% \xdef\currentstructuresynchronize{\strc_lists_inject_enhance{#1}}}
+
\unexpanded\def\setstructuresynchronization#1% todo: use ctxcontext
{\clf_setinternalreference
prefix {\currentstructurereferenceprefix}%
@@ -26,7 +36,20 @@
internal \locationcount
view {\interactionparameter\c!focus}%
\relax
- \xdef\currentstructureattribute {\the\lastdestinationattribute}%
- \xdef\currentstructuresynchronize{\strc_lists_inject_enhance{#1}{\the\locationcount}}}
+ \xdef\currentstructureattribute
+ {\the\lastdestinationattribute}%
+ \xdef\currentstructuresynchronize
+ {\currentstructuresynchronize
+ \strc_lists_inject_enhance{#1}}}
+
+\unexpanded\def\setstructurecomponentsynchronization#1% todo: use ctxcontext
+ {\clf_setinternalreference
+ prefix {\currentstructurecomponentreferenceprefix}%
+ reference {\currentstructurecomponentreference}
+ internal \locationcount
+ view {\interactionparameter\c!focus}%
+ \relax
+ \xdef\currentstructurecomponentattribute {\the\lastdestinationattribute}%
+ \xdef\currentstructurecomponentsynchronize{\strc_lists_inject_enhance{#1}}}
\protect \endinput
diff --git a/tex/context/base/mkiv/strc-flt.lua b/tex/context/base/mkiv/strc-flt.lua
index 466fd515e..e3a0ea30e 100644
--- a/tex/context/base/mkiv/strc-flt.lua
+++ b/tex/context/base/mkiv/strc-flt.lua
@@ -7,3 +7,37 @@ if not modules then modules = { } end modules ['strc-flt'] = {
}
-- nothing
+
+local sequencers = utilities.sequencers
+local appendaction = sequencers.appendaction
+local enableaction = sequencers.enableaction
+local disableaction = sequencers.disableaction
+
+local texgetdimen = tex.getdimen
+
+local trace = trackers.register("structure.sidefloats.pageflush")
+local report = logs.reporter("structure","floats")
+
+local forcepageflush = builders.vspacing.forcepageflush
+
+function builders.checksidefloat(mode,indented)
+ local s = texgetdimen("d_page_sides_vsize")
+ if s > 0 then
+ if trace then
+ report("force flushing page state, height %p",s)
+ end
+ forcepageflush()
+ end
+ return indented
+end
+
+appendaction ("newgraf","system","builders.checksidefloat")
+disableaction("newgraf","builders.checksidefloat")
+
+interfaces.implement {
+ name = "enablesidefloatchecker",
+ onlyonce = true,
+ actions = function()
+ enableaction("newgraf","builders.checksidefloat")
+ end,
+}
diff --git a/tex/context/base/mkiv/strc-flt.mkvi b/tex/context/base/mkiv/strc-flt.mkvi
index 632c67686..02f6fd753 100644
--- a/tex/context/base/mkiv/strc-flt.mkvi
+++ b/tex/context/base/mkiv/strc-flt.mkvi
@@ -61,9 +61,11 @@
\installcorenamespace{float}
\installcorenamespace{floatbuilder}
\installcorenamespace{floatcaption}
+\installcorenamespace{floatframed}
\installframedcommandhandler \??float {float} \??float
\installframedcommandhandler \??floatcaption {floatcaption} \??floatcaption
+\installframedcommandhandler \??floatframed {floatframed} \??floatframed
\let\setupfloats \setupfloat
\let\setupcaption \setupfloatcaption
@@ -97,6 +99,8 @@
\c!textcolor=,
\c!align=,
\c!number=\v!yes,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off,
% \c!expansion=,
% \c!prefix=,
% \c!prefixconnector=,
@@ -110,7 +114,7 @@
% \c!stopper=,
\c!suffixseparator=, % currently rather hard coded
\c!suffix=\floatcaptionsuffix,
- \c!distance=\emwidth,
+ \c!distance=\emwidth, % plus .5\emwidth minus .25\emwidth
\c!conversion=\v!numbers,
\c!maxwidth=\hsize,
\c!command=]
@@ -171,6 +175,11 @@
\c!sidethreshold=.5\strutdp, % set to "old" to check with old method
\c!numbering=\v!yes]
+\setupfloatframed
+ [\c!frame=\v!off,
+ \c!offset=\v!overlay,
+ \c!strut=\v!no]
+
%D Individial settings:
\installcounterassociation{floatcaption}
@@ -207,6 +216,7 @@
\def\strc_floats_define_a[#1][#2][#3]% name names parent
{\definefloatcaption[#1][#3]%
+ \definefloatframed[#1][#3]%
\definecounter[#1][#3]%
\definelist[#1][#3]%
\copylabeltext[#1=#3]%
@@ -215,6 +225,7 @@
\def\strc_floats_define_b[#1][#2][#3]% name parent settings
{\definefloatcaption[#1][#2]%
+ \definefloatframed[#1][#2]%
\definecounter[#1][#2]%
\definelist[#1][#2]%
\copylabeltext[#1=#2]%
@@ -224,6 +235,7 @@
\def\strc_floats_define_c[#1][#2]% name names
{\registerfloatcaptioncounter{#1}%
\definefloatcaption[#1]%
+ \definefloatframed[#1]%
\definecounter[#1]%
\definelist[#1]%
\presetlabeltext[#1=\Word{#1}~]%
@@ -332,6 +344,7 @@
\def\strc_floats_make_complete_caption
{\doifsomething{\floatcaptionparameter\c!spacebefore}{\blank[\floatcaptionparameter\c!spacebefore]}%
+ \strc_floats_make_complete_caption_before
\synchronizedisplaydirection % temp hack, till we have a proper model
\noindent
\gdef\lastcaptiontag{\strut\thecurrentfloatnumber}% was xdef ... needs checking
@@ -361,8 +374,26 @@
\thecurrentfloatcaption\endgraf
\fi
\endgroup
+ \strc_floats_make_complete_caption_after
\doifsomething{\floatcaptionparameter\c!spaceafter}{\blank[\floatcaptionparameter\c!spaceafter]}}
+%let\strc_floats_make_complete_caption_before\relax
+\let\strc_floats_make_complete_caption_after \relax
+
+\def\strc_floats_make_complete_caption_before
+ {\doifelseframed\floatcaptionparameter\strc_floats_make_complete_caption_before_indeed\relax}
+
+\def\strc_floats_make_complete_caption_before_indeed
+ {\edef\m_strc_align{\floatcaptionparameter\c!align}%
+ \edef\m_strc_strut{\floatcaptionparameter\c!strut}%
+ \letfloatcaptionparameter\c!align\v!normal
+ \letfloatcaptionparameter\c!strut\v!no
+ \inheritedfloatcaptionframed
+ \bgroup
+ \letfloatcaptionparameter\c!align\m_strc_align
+ \letfloatcaptionparameter\c!strut\m_strc_strut
+ \let\strc_floats_make_complete_caption_after\egroup}
+
% \definefloat [figure-1] [figure]
% \definefloat [figure-2] [figure]
% \setupfloat [figure-1] [location=left,leftmargin=10mm]
@@ -425,7 +456,7 @@
%D {\global\advance\c_strc_floats_n\plusone
%D \xdef\strc_float_realpage{\datasetvariable\s!float{\number\c_strc_floats_n}\s!page}%
%D \ifx\strc_float_realpage\empty
-%D \globallet\strc_float_realpage\realpageno % \realfolio
+%D \glet\strc_float_realpage\realpageno % \realfolio
%D \fi}
%D \stoptyping
%D
@@ -444,7 +475,7 @@
{\global\advance\c_strc_floats_n\plusone
\xdef\strc_float_realpage{\pagestaterealpage\s!float{\number\c_strc_floats_n}}%
\ifx\strc_float_realpage\empty
- \globallet\strc_float_realpage\realpageno % \realfolio
+ \glet\strc_float_realpage\realpageno % \realfolio
\fi}
%D test case:
@@ -482,7 +513,7 @@
\donothing
{\writestatus\m!floatblocks{unknown float type '\currentfloat'}%
\let\currentfloat\v!figure}% also a hack
- \global\let\lastplacedfloat\currentfloat
+ \glet\lastplacedfloat\currentfloat
\let\m_strc_floats_saved_userdata\empty
\let\currentfloatcaption\currentfloat}
@@ -493,8 +524,8 @@
{\global\emptyfloatcaptionfalse
\global\nofloatcaptionfalse
\global\nofloatnumberfalse
- \global\let\askedfloatmethod \empty
- \global\let\askedfloatoptions\empty}
+ \glet\askedfloatmethod \empty
+ \glet\askedfloatoptions\empty}
% place
@@ -505,10 +536,13 @@
\let\floatlocationmethod\empty
\def\strc_floats_analyze_location
- {% moved here, will do more
+ {% more will be moved here
\let\floatlabel \empty
\let\floatcolumn\empty
\let\floatrow \empty
+ %
+ \edef\floatcaptionlocation{\floatcaptionparameter\c!location}%
+ %
\setfloatmethodvariables\floatlocation}
\unexpanded\def\strc_floats_place#tag%
@@ -571,25 +605,49 @@
\strc_floats_set_current_tag{#tag}%
\dodoubleempty\strc_floats_start_place_indeed}
+%D We abuse the settings to pick up some float parameters too which makes it
+%D messy.
+
\def\strc_floats_start_place_indeed[#settings][#userdata]%
{\strc_floats_reset_variables
- \edef\savedfloatlocation{\floatcaptionparameter\c!location}%
+ % save
+ \edef\m_location {\floatcaptionparameter\c!location}%
+ \edef\m_topoffset {\floatcaptionparameter\c!topoffset}%
+ \edef\m_bottomoffset{\floatcaptionparameter\c!bottomoffset}%
+ \edef\m_freeregion {\floatcaptionparameter\c!freeregion}%
+ % preset
+ \letfloatcaptionparameter \c!location \empty
\setexpandedfloatcaptionparameter\c!topoffset {\floatparameter\c!topoffset}%
\setexpandedfloatcaptionparameter\c!bottomoffset{\floatparameter\c!bottomoffset}%
\setexpandedfloatcaptionparameter\c!freeregion {\floatparameter\c!freeregion}%
- \setupcurrentfloatcaption[\c!location=,\c!reference=,\c!title=,\c!marking=,\c!list=,\c!bookmark=,#settings]%
- \setexpandedfloatparameter\c!topoffset {\floatcaptionparameter\c!topoffset}%
- \setexpandedfloatparameter\c!bottomoffset{\floatcaptionparameter\c!bottomoffset}%
- \setexpandedfloatparameter\c!freeregion {\floatcaptionparameter\c!freeregion}%
- \def\m_strc_floats_saved_userdata{#2}%
+ \letfloatcaptionparameter \c!reference \empty
+ \letfloatcaptionparameter \c!title \empty
+ \letfloatcaptionparameter \c!marking \empty
+ \letfloatcaptionparameter \c!list \empty
+ \letfloatcaptionparameter \c!bookmark \empty
+ % pickup
+ \setupcurrentfloatcaption[#settings]%
+ \ifsecondargument
+ \setupcurrentfloatuserdata[#userdata]%
+ \def\m_strc_floats_saved_userdata{#userdata}%
+ \else
+ \let\m_strc_floats_saved_userdata\empty
+ \fi
+ % check
\edef\floatlocation{\floatcaptionparameter\c!location}%
- \setfloatcaptionparameter\c!location{\savedfloatlocation}% not expanded
\ifx\floatlocation\empty
\edef\floatlocation{\floatparameter\c!default}%
\fi
- \ifsecondargument
- \setupcurrentfloatuserdata[#userdata]%
- \fi
+ % inherit
+ \setexpandedfloatparameter\c!topoffset {\floatcaptionparameter\c!topoffset}%
+ \setexpandedfloatparameter\c!bottomoffset{\floatcaptionparameter\c!bottomoffset}%
+ \setexpandedfloatparameter\c!freeregion {\floatcaptionparameter\c!freeregion}%
+ % restore
+ \letfloatcaptionparameter\c!location \m_location
+ \letfloatcaptionparameter\c!topoffset \m_topoffset
+ \letfloatcaptionparameter\c!bottomoffset\m_bottomoffset
+ \letfloatcaptionparameter\c!freeregion \m_freeregion
+ %
\strc_floats_analyze_location
\doifelseinset\v!split\floatlocation\strc_floats_place_next_box_split\strc_floats_place_next_box_normal
\bgroup
@@ -928,9 +986,9 @@
\def\strc_floats_place_packaged_boxes_indeed#userdata%
{\bgroup
\ifconditional\usesamefloatnumber
- \globallet\currentfloatnumber \previousfloatnumber
- \globallet\currentfloatattribute \empty
- \globallet\currentfloatsynchronize\relax
+ \glet\currentfloatnumber \previousfloatnumber
+ \glet\currentfloatattribute \empty
+ \glet\currentfloatsynchronize\relax
\else
\edef\currentfloatcounter{\namedcounterparameter\currentfloat\s!name}%
\edef\currentfloatgroup {\floatcaptionparameter\c!group}%
@@ -962,10 +1020,10 @@
\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
- \globallet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize
+ \glet\previousfloatnumber \m_strc_counters_last_registered_index
+ \glet\currentfloatnumber \m_strc_counters_last_registered_index
+ \glet\currentfloatattribute \m_strc_counters_last_registered_attribute
+ \glet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize
\fi
%
\global\setfalse\usesamefloatnumber % one shot
@@ -1191,11 +1249,11 @@
{\global\setbox\floatbox\hpack to \scratchwidth
{\doifnotinset\v!right\floatlocation\hss
\box\floatbox
- \doifnotinset\v!left \floatlocation\hss}}
+ \doifnotinset\v!left\floatlocation\hss}}
-\def\strc_floats_realign_floatbox_horizontal_two
+\def\strc_floats_realign_floatbox_horizontal_two % why is this
{\global\setbox\floatbox\hpack to \scratchwidth
- {\doifnot{\floatparameter\c!location}\v!left \hss
+ {\doifnot{\floatparameter\c!location}\v!left\hss
\box\floatbox
\doifnot{\floatparameter\c!location}\v!right\hss}}
@@ -1336,7 +1394,7 @@
%
% \def\strc_floats_align_content_indeed
% {\alignstrutmode\zerocount
-% \doifnotcommon{\floatcaptionparameter\c!location}{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin}
+% \doifnotcommon\floatcaptionlocation{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin}
% {\shiftalignedline
% {\floatparameter\c!leftmargin }{\floatparameter\c!rightmargin}%
% {\floatparameter\c!innermargin}{\floatparameter\c!outermargin}}%
@@ -1371,7 +1429,7 @@
\def\strc_floats_align_content_indeed
{\alignstrutmode\zerocount
\ifx\forcedfloatmethod\v!local \else
- \doifnotcommon{\floatcaptionparameter\c!location}{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin}
+ \doifnotcommon\floatcaptionlocation{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin}
{\strc_floats_shift_indeed\floatparameter}%
\expandafter\strc_floats_align_indeed
\fi}
@@ -1462,23 +1520,21 @@
\fi\fi
\strc_floats_align_content{\copy\b_strc_floats_content}}}
+
\def\strc_floats_prepare_page_caption
- {\edef\p_strc_floats_caption_location{\floatcaptionparameter\c!location}%
- \edef\p_strc_floats_caption_width {\floatcaptionparameter\c!width}%
+ {\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
+ \doifcommonelse\floatcaptionlocation{\v!top,\v!bottom}
+ {\strc_floats_prepare_page_caption_top_bottom}
+ {\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}%
\dostoptagged}
\def\strc_floats_prepare_page_caption_top_bottom
@@ -1508,7 +1564,11 @@
\fi}
\def\strc_floats_caption_set_align
- {\normalexpanded{\setupalign[\v!reset,\p_strc_floats_caption_align]}}
+ {\edef\m_align{\v!reset\ifx\p_strc_floats_caption_align\empty\else,\fi\p_strc_floats_caption_align}%
+ \doifinset\v!tolerant \floatcaptionlocation{\edef\m_align{\m_align,\v!tolerant}}%
+ \doifinset\v!verytolerant\floatcaptionlocation{\edef\m_align{\m_align,\v!verytolerant}}%
+ \doifinset\v!stretch \floatcaptionlocation{\edef\m_align{\m_align,\v!stretch}}%
+ \setupalign[\m_align]}
\def\strc_floats_prepare_side_auto_caption
{\scratchdimen\dimexpr\hsize-\wd\b_strc_floats_content-\floatparameter\c!margin\relax
@@ -1640,7 +1700,7 @@
{\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi % skip, no pack
{\d_strc_float_temp_height\ht\b_strc_floats_content
\box\b_strc_floats_content
- \doifnotinset\v!hang{\floatcaptionparameter\c!location}
+ \doifnotinset\v!hang\floatcaptionlocation
{\dotfskip{\floatcaptionparameter\c!distance}}%
\vbox to\d_strc_float_temp_height{#1}}}
@@ -1648,7 +1708,7 @@
{\ifconditional\c_strc_floats_par_float \hbox \else \expandafter \strc_floats_align_content \fi % skip, no pack
{\d_strc_float_temp_height\ht\b_strc_floats_content
\vbox to\d_strc_float_temp_height{#1}%
- \doifnotinset\v!hang{\floatcaptionparameter\c!location}
+ \doifnotinset\v!hang\floatcaptionlocation
{\dotfskip{\floatcaptionparameter\c!distance}}%
\box\b_strc_floats_content}}
@@ -1718,7 +1778,7 @@
\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]
+ \processallactionsinset[\floatcaptionlocation]
[ \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,
@@ -1736,7 +1796,7 @@
\let\next\strc_floats_build_box_high
\else
\let\next\strc_floats_build_box_middle
- \processallactionsinset[\floatcaptionparameter\c!location]
+ \processallactionsinset[\floatcaptionlocation]
[ \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]%
@@ -1749,14 +1809,13 @@
\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
- {\edef\p_strc_floats_caption_location{\floatcaptionparameter\c!location}%
- \doifelseinset\v!righthanging\p_strc_floats_caption_location
+\def\strc_floats_flush_caption_hang
+ {\doifelseinset\v!righthanging\floatcaptionlocation
{\strc_floats_flush_right_caption_hang}
- {\doifelseinset\v!lefthanging\p_strc_floats_caption_location
+ {\doifelseinset\v!lefthanging\floatcaptionlocation
{\strc_floats_flush_left_caption_hang}
- {\doifelseinset\v!hang\p_strc_floats_caption_location
- {\doifelseinset\v!outer\p_strc_floats_caption_location
+ {\doifelseinset\v!hang\floatcaptionlocation
+ {\doifelseinset\v!outer\floatcaptionlocation
{\doifelserightpagefloat{\strc_floats_flush_right_caption_hang}{\strc_floats_flush_left_caption_hang}}
{\doifelseinset\v!right\floatcaptiondirectives
{\strc_floats_flush_right_caption_hang}
@@ -1834,6 +1893,7 @@
{\dp\b_strc_floats_caption\strutdepth
\setbox\scratchbox\vbox
{\d_strc_float_temp_width\wd\b_strc_floats_content
+ \hsize\d_strc_float_temp_width
\ifconditional\c_strc_floats_par_float
\strc_floats_locate_side_float{\box\b_strc_floats_caption}%
\vss\strc_floats_between_stack
@@ -1845,12 +1905,13 @@
\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}} % \vpack ?
+ \vpack to \noflines\lineheight{\unvbox\scratchbox}}
\def\strc_floats_build_box_bottom_stack_grid
{\dp\b_strc_floats_caption\strutdepth
\setbox\scratchbox\vbox
{\d_strc_float_temp_width\wd\b_strc_floats_content
+ \hsize\d_strc_float_temp_width
\ifconditional\c_strc_floats_par_float
\hpack{\box\b_strc_floats_content}%
\vss\strc_floats_between_stack
@@ -1862,7 +1923,7 @@
\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}} % \vpack ?
+ \vpack to \noflines\lineheight{\unvbox\scratchbox}}
\def\strc_floats_build_box_top_stack_stretch
{\dp\b_strc_floats_caption\strutdepth
@@ -1872,6 +1933,7 @@
\getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
\vbox to \noflines\lineheight % pack ?
{\d_strc_float_temp_width\wd\b_strc_floats_content
+ \hsize\d_strc_float_temp_width
\ifconditional\c_strc_floats_par_float
\strc_floats_locate_side_float{\box\b_strc_floats_caption}%
\vss\strc_floats_between_stack\vss
@@ -1885,16 +1947,17 @@
\def\strc_floats_build_box_bottom_stack_stretch
{\dp\b_strc_floats_caption\strutdepth
- \setbox\scratchbox\vbox % pack ?
- {\strc_floats_align_content{\copy\b_strc_floats_content }%
+ \setbox\scratchbox\vpack
+ {\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
{\d_strc_float_temp_width\wd\b_strc_floats_content
+ \hsize\d_strc_float_temp_width
\ifconditional\c_strc_floats_par_float
\hpack{\box\b_strc_floats_content}%
\vss\strc_floats_between_stack\vss
- \strc_floats_locate_side_float{\box\b_strc_floats_caption}
+ \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}%
@@ -1906,14 +1969,14 @@
{\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]%
+ \v!lines=>\let\next\strc_floats_build_box_top_stack_stretch]% was \v!grid but interfered
\next}
\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]%
+ \v!lines=>\let\next\strc_floats_build_box_bottom_stack_stretch]% was \v!grid but interfered
\next}
\def\strc_floats_relocate_caption_right#1{\strc_floats_align_caption{\hbox to \d_strc_float_temp_width{\hss#1}}}
@@ -1921,23 +1984,50 @@
\unexpanded\def\installfloatboxbuilder#1#2{\setvalue{\??floatbuilder#1}{#2}}
-\let\strc_floats_mark_box_as_free\relax
-
\def\strc_floats_build_box
- {\global\setbox\floatbox\vbox % pack ? probably not
+ {\strc_floats_build_box_before
+ \global\setbox\floatbox\vbox % pack ? probably not
{\strc_floats_set_local_hsize
\forgetall
\ifconditional\c_floats_store_minimal_package
\strc_floats_build_box_separate_make
\else
- \let\floatcaptionarrangement\s!default
+ % \let\floatcaptionarrangement\s!default
+ \let\floatcaptionarrangement\v!bottom % for Alan
\processcommacommand[\floatcaptionparameter\c!location]\strc_floats_build_box_step
\ifcsname\??floatbuilder\floatcaptionarrangement\endcsname
\lastnamedcs
\else
\strc_floats_build_box_default
\fi
- \fi}}
+ \fi}%
+ \strc_floats_build_box_after}
+
+% \let\strc_floats_build_box_before\relax
+% \let\strc_floats_build_box_after \relax
+
+\def\strc_floats_build_box_before
+ {\let\currentfloatframed\currentfloat
+ \floatwidth\wd
+ \ifdim\wd\b_strc_floats_content>\wd\b_strc_floats_caption
+ \b_strc_floats_content\else\b_strc_floats_caption
+ \fi}
+
+\def\strc_floats_build_box_after
+ {\doifelseframed\floatframedparameter\strc_floats_build_box_after_indeed\relax}
+
+\def\strc_floats_build_box_after_indeed
+ {\global\setbox\floatbox\hpack
+ {\edef\m_width{\floatframedparameter\c!width}%
+ \ifx\m_width\v!fit
+ \let\m_width\floatwidth
+ \else\ifx\m_width\v!broad
+ \let\m_width\v!fit
+ \fi\fi
+ \letfloatframedparameter\c!strut\v!no
+ \letfloatframedparameter\c!width\m_width
+ \inheritedfloatframedframed
+ {\box\floatbox}}}
% special purpose: used in floatcombinations
@@ -1954,7 +2044,7 @@
\vpack to \onepoint{\box\b_strc_floats_caption}}
\def\strc_floats_build_box_separate_split#1%
- {\setbox\scratchbox\vbox{%
+ {\setbox\scratchbox\vbox\bgroup
\setbox\scratchbox\vpack{#1}%
\unvbox\scratchbox\relax
\setbox\scratchbox\lastbox
@@ -1965,13 +2055,20 @@
\unvbox\scratchbox
\setbox\scratchbox\lastbox
% \exitloop
- % \fi}%
+ % \fi
+ %}%
\splittopskip\zeropoint
\global\setbox\b_strc_floats_separate_content\vsplit\scratchbox to \onepoint
\global\setbox\b_strc_floats_separate_caption\vsplit\scratchbox to \onepoint
- \global\setbox\b_strc_floats_separate_content\vpack{\unvbox\b_strc_floats_separate_content\setbox0\lastbox\unvbox0}%
- \global\setbox\b_strc_floats_separate_caption\tpack{\unvbox\b_strc_floats_separate_caption\setbox0\lastbox\unvbox0}%
- }}
+ \egroup
+ \global\setbox\b_strc_floats_separate_content\vpack
+ {\unvbox\b_strc_floats_separate_content
+ \setbox\scratchbox\lastbox
+ \unvbox\scratchbox}%
+ \global\setbox\b_strc_floats_separate_caption\tpack
+ {\unvbox\b_strc_floats_separate_caption
+ \setbox\scratchbox\lastbox
+ \unvbox\scratchbox}}
% \def\strc_floats_build_box_step#1%
% {\doifdefined{\??floatbuilder#1}{\def\floatcaptionarrangement{#1}\quitcommalist}}
@@ -2105,8 +2202,9 @@
\def\strc_floats_prepare_side_caption_fit % or center when smaller
{\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content\relax
- \setbox\b_strc_floats_caption\vbox
+ \setbox\b_strc_floats_caption\vbox
{\forgetall % needed?
+ \strc_floats_caption_set_align
\hsize\wd\b_strc_floats_content
\strc_floats_make_complete_caption}%
\else
@@ -2295,6 +2393,8 @@
\definesystemconstant{fxbt}
\definesystemconstant{fixd}
+% can move to page-one:
+
\installfloatmethod \s!singlecolumn \v!here \page_one_place_float_here
\installfloatmethod \s!singlecolumn \v!force \page_one_place_float_force
\installfloatmethod \s!singlecolumn \v!left \page_one_place_float_left
@@ -2330,76 +2430,6 @@
\installfloatmethod \s!singlecolumn \s!fxbt \page_one_place_float_bottom
\installfloatmethod \s!singlecolumn \s!fixd \page_one_place_float_force
-\installfloatmethod \s!multicolumn \v!here \page_mul_place_float_here
-\installfloatmethod \s!multicolumn \v!force \page_mul_place_float_force
-%installfloatmethod \s!multicolumn \v!left
-%installfloatmethod \s!multicolumn \v!right
-%installfloatmethod \s!multicolumn \v!text
-\installfloatmethod \s!multicolumn \v!top \page_mul_place_float_top
-\installfloatmethod \s!multicolumn \v!bottom \page_mul_place_float_bottom
-%installfloatmethod \s!multicolumn \v!auto
-%installfloatmethod \s!multicolumn \v!margin
-%installfloatmethod \s!multicolumn \v!opposite
-%installfloatmethod \s!multicolumn \v!page
-%installfloatmethod \s!multicolumn \v!leftpage
-%installfloatmethod \s!multicolumn \v!rightpage
-%installfloatmethod \s!multicolumn \v!inmargin
-%installfloatmethod \s!multicolumn \v!inleft
-%installfloatmethod \s!multicolumn \v!inright
-%installfloatmethod \s!multicolumn \v!leftmargin
-%installfloatmethod \s!multicolumn \v!rightmargin
-%installfloatmethod \s!multicolumn \v!leftedge
-%installfloatmethod \s!multicolumn \v!rightedge
-%installfloatmethod \s!multicolumn \v!somewhere
-%installfloatmethod \s!multicolumn \v!backspace
-%installfloatmethod \s!multicolumn \v!cutspace
-%installfloatmethod \s!multicolumn \s!tblr
-%installfloatmethod \s!multicolumn \s!lrtb
-%installfloatmethod \s!multicolumn \s!tbrl
-%installfloatmethod \s!multicolumn \s!rltb
-%installfloatmethod \s!multicolumn \s!fxtb
-%installfloatmethod \s!multicolumn \s!btlr
-%installfloatmethod \s!multicolumn \s!lrbt
-%installfloatmethod \s!multicolumn \s!btrl
-%installfloatmethod \s!multicolumn \s!rlbt
-%installfloatmethod \s!multicolumn \s!fxbt
-%installfloatmethod \s!multicolumn \s!fixd
-
-\installfloatmethod \s!columnset \v!here \page_set_place_float_here
-\installfloatmethod \s!columnset \v!force \page_set_place_float_force
-%installfloatmethod \s!columnset \v!left
-%installfloatmethod \s!columnset \v!right
-%installfloatmethod \s!columnset \v!text
-\installfloatmethod \s!columnset \v!top \page_set_place_float_top
-\installfloatmethod \s!columnset \v!bottom \page_set_place_float_bottom
-%installfloatmethod \s!columnset \v!auto
-%installfloatmethod \s!columnset \v!margin
-%installfloatmethod \s!columnset \v!opposite
-\installfloatmethod \s!columnset \v!page \page_set_place_float_page
-%installfloatmethod \s!columnset \v!leftpage
-%installfloatmethod \s!columnset \v!rightpage
-%installfloatmethod \s!columnset \v!inmargin
-%installfloatmethod \s!columnset \v!inleft
-%installfloatmethod \s!columnset \v!inright
-%installfloatmethod \s!columnset \v!leftmargin
-%installfloatmethod \s!columnset \v!rightmargin
-%installfloatmethod \s!columnset \v!leftedge
-%installfloatmethod \s!columnset \v!rightedge
-%installfloatmethod \s!columnset \v!somewhere
-%installfloatmethod \s!columnset \v!backspace
-%installfloatmethod \s!columnset \v!cutspace
-\installfloatmethod \s!columnset \s!tblr \page_set_place_float_slot
-\installfloatmethod \s!columnset \s!lrtb \page_set_place_float_slot
-\installfloatmethod \s!columnset \s!tbrl \page_set_place_float_slot
-\installfloatmethod \s!columnset \s!rltb \page_set_place_float_slot
-\installfloatmethod \s!columnset \s!fxtb \page_set_place_float_slot
-\installfloatmethod \s!columnset \s!btlr \page_set_place_float_slot
-\installfloatmethod \s!columnset \s!lrbt \page_set_place_float_slot
-\installfloatmethod \s!columnset \s!btrl \page_set_place_float_slot
-\installfloatmethod \s!columnset \s!rlbt \page_set_place_float_slot
-\installfloatmethod \s!columnset \s!fxbt \page_set_place_float_slot
-\installfloatmethod \s!columnset \s!fixd \page_set_place_float_force
-
%D Local floats:
\installcorenamespace{localfloats}
diff --git a/tex/context/base/mkiv/strc-itm.mkvi b/tex/context/base/mkiv/strc-itm.mkvi
index 0bea62de8..0fc204320 100644
--- a/tex/context/base/mkiv/strc-itm.mkvi
+++ b/tex/context/base/mkiv/strc-itm.mkvi
@@ -352,8 +352,8 @@
\csname\??itemgroupsetting\currentitemgroup\endcsname}
\def\strc_itemgroups_reset_continue_state
- {\global\expandafter\let\csname\??itemgroupoption \currentitemgroup\endcsname\relax
- \global\expandafter\let\csname\??itemgroupsetting\currentitemgroup\endcsname\relax}
+ {\expandafter\glet\csname\??itemgroupoption \currentitemgroup\endcsname\relax
+ \expandafter\glet\csname\??itemgroupsetting\currentitemgroup\endcsname\relax}
% These will become keywords. We will also add a feature to keep the while set
% together.
diff --git a/tex/context/base/mkiv/strc-lnt.mkvi b/tex/context/base/mkiv/strc-lnt.mkvi
index cd10c9def..4a6f14245 100644
--- a/tex/context/base/mkiv/strc-lnt.mkvi
+++ b/tex/context/base/mkiv/strc-lnt.mkvi
@@ -242,13 +242,13 @@
\def\strc_linenotes_traced_indeed#1%
{\iftracelinenotes
- \hbox to \zeropoint
+ \hpack to \zeropoint
{\forgetall
\hsize\zeropoint
\hss
- \vbox to \strutheight{\llap{\red\infofont\setstrut\the\c_strc_linenotes}\vss}%
+ \vpack to \strutheight{\llap{\red\infofont\setstrut\the\c_strc_linenotes}\vss}%
{\color[blue]{\vl}}%
- \vbox to \strutheight{\rlap{\red\infofont\setstrut#1}\vss}%
+ \vpack to \strutheight{\rlap{\red\infofont\setstrut#1}\vss}%
\hss}%
\prewordbreak
\fi}
diff --git a/tex/context/base/mkiv/strc-lst.lua b/tex/context/base/mkiv/strc-lst.lua
index 13bdf7786..bc6135e72 100644
--- a/tex/context/base/mkiv/strc-lst.lua
+++ b/tex/context/base/mkiv/strc-lst.lua
@@ -35,6 +35,8 @@ local commands = commands
local implement = interfaces.implement
local conditionals = tex.conditionals
+local ctx_latelua = context.latelua
+
local structures = structures
local lists = structures.lists
local sections = structures.sections
@@ -97,7 +99,8 @@ local v_default = variables.default
-- for the moment not public --
local function zerostrippedconcat(t,separator)
- local f, l = 1, #t
+ local f = 1
+ local l = #t
for i=f,l do
if t[i] == 0 then
f = f + 1
@@ -307,7 +310,8 @@ local synchronizepage = function(r) -- bah ... will move
return synchronizepage(r)
end
-function lists.enhance(n)
+local function enhancelist(specification)
+ local n = specification.n
local l = cached[n]
if not l then
report_lists("enhancing %a, unknown internal",n)
@@ -348,6 +352,8 @@ function lists.enhance(n)
end
end
+lists.enhance = enhancelist
+
-- we can use level instead but we can also decide to remove level from the metadata
local nesting = { }
@@ -847,18 +853,22 @@ end
function lists.userdata(name,r,tag) -- to tex (todo: xml)
local result = lists.result[r]
if result then
- local userdata, metadata = result.userdata, result.metadata
+ local userdata = result.userdata
local str = userdata and userdata[tag]
if str then
- return str, metadata
+ return str, result.metadata
end
end
end
function lists.uservalue(name,r,tag,default) -- to lua
local str = lists.result[r]
- str = str and str.userdata
- str = str and str[tag]
+ if str then
+ str = str.userdata
+ end
+ if str then
+ str = str[tag]
+ end
return str or default
end
@@ -1071,8 +1081,19 @@ implement {
implement {
name = "enhancelist",
- actions = lists.enhance,
- arguments = "integer"
+ arguments = "integer",
+ actions = function(n)
+ enhancelist { n = n }
+ end
+}
+
+implement {
+ name = "deferredenhancelist",
+ arguments = "integer",
+ protected = true, -- for now, pre 1.09
+ actions = function(n)
+ ctx_latelua { action = enhancelist, n = n }
+ end,
}
implement {
diff --git a/tex/context/base/mkiv/strc-lst.mkvi b/tex/context/base/mkiv/strc-lst.mkvi
index 153d879b7..7bc859b67 100644
--- a/tex/context/base/mkiv/strc-lst.mkvi
+++ b/tex/context/base/mkiv/strc-lst.mkvi
@@ -145,8 +145,9 @@
{\endgroup}
% \unexpanded
-\def\strc_lists_inject_enhance#listindex#internal%
- {\normalexpanded{\ctxlatecommand{enhancelist(\number#listindex)}}}
+
+\def\strc_lists_inject_enhance#listindex%
+ {\expandafter\clf_deferredenhancelist\number#listindex\relax}
\unexpanded\def\strc_lists_inject_yes[#settings][#userdata]% can be used directly
{\setupcurrentlist[\c!type=userdata,\c!location=\v!none,#settings]% grouped (use \let...
@@ -168,16 +169,16 @@
userdata {\detokenize\expandafter{\normalexpanded{#userdata}}}
\relax
\edef\currentlistnumber{\the\scratchcounter}%
-\setxvalue{\??listlocations\currentlist}{\the\locationcount}%
+ \setxvalue{\??listlocations\currentlist}{\the\locationcount}%
\ifx\p_location\v!here
% this branch injects nodes !
- \strc_lists_inject_enhance{\currentlistnumber}{\the\locationcount}%
+ \strc_lists_inject_enhance{\currentlistnumber}%
\clf_setinternalreference
internal \locationcount
view {\interactionparameter\c!focus}%
\relax % this will change
\xdef\currentstructurelistattribute{\the\lastdestinationattribute}%
- \dontleavehmode\hbox attr \destinationattribute \lastdestinationattribute{}% todo
+ \dontleavehmode\hpack attr \destinationattribute \lastdestinationattribute{}% todo
\else
% and this one doesn't
\clf_enhancelist\currentlistnumber\relax
@@ -467,7 +468,7 @@
\relax}
\def\firststructureelementinlist#list% expandable
- {\clf_firstinset{#list}}
+ {\firstinset{#list}}
\def\structurelistsize
{\clf_listsize}
@@ -871,7 +872,7 @@
\appendtoks
\dontcomplain
- \letinteractionparameter\c!width\zeropoint % a weird one
+ % \letinteractionparameter\c!width\zeropoint % a weird one
\to \t_lists_every_renderingsetup
\appendtoks
@@ -1091,7 +1092,7 @@
\fi
\ifconditional\c_lists_has_page
\ifconditional\c_lists_show_page
- \setbox\b_strc_lists_page\hbox {
+ \setbox\b_strc_lists_page\hpack {
\scratchdimen\listalternativeparameter\c!width
\hbox \strc_lists_get_reference_attribute\v!pagenumber \ifdim\scratchdimen>\zeropoint to \scratchdimen\fi {
\hfill
diff --git a/tex/context/base/mkiv/strc-mar.lua b/tex/context/base/mkiv/strc-mar.lua
index 24a7fd491..0221b9b8f 100644
--- a/tex/context/base/mkiv/strc-mar.lua
+++ b/tex/context/base/mkiv/strc-mar.lua
@@ -13,78 +13,82 @@ local insert, concat = table.insert, table.concat
local tostring, next, rawget, type = tostring, next, rawget, type
local lpegmatch = lpeg.match
-local context = context
-local commands = commands
+local context = context
+local commands = commands
-local implement = interfaces.implement
+local implement = interfaces.implement
-local allocate = utilities.storage.allocate
-local setmetatableindex = table.setmetatableindex
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
-local nuts = nodes.nuts
-local tonut = nuts.tonut
+local nuts = nodes.nuts
+local tonut = nuts.tonut
-local getid = nuts.getid
-local getlist = nuts.getlist
-local getattr = nuts.getattr
-local getbox = nuts.getbox
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getattr = nuts.getattr
+local getbox = nuts.getbox
-local traverse = nuts.traverse
-local traverse_id = nuts.traverse_id
+local nextnode = nuts.traversers.node
-local nodecodes = nodes.nodecodes
-local glyph_code = nodecodes.glyph
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
+local nodecodes = nodes.nodecodes
+local whatsitcodes = nodes.whatsitcodes
-local texsetattribute = tex.setattribute
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local whatsit_code = nodecodes.whatsit
-local a_marks = attributes.private("structure","marks")
+local lateluawhatsit_code = whatsitcodes.latelua
-local trace_marks_set = false trackers.register("marks.set", function(v) trace_marks_set = v end)
-local trace_marks_get = false trackers.register("marks.get", function(v) trace_marks_get = v end)
-local trace_marks_all = false trackers.register("marks.detail", function(v) trace_marks_all = v end)
+local texsetattribute = tex.setattribute
-local report_marks = logs.reporter("structure","marks")
+local a_marks = attributes.private("structure","marks")
-local variables = interfaces.variables
+local trace_marks_set = false trackers.register("marks.set", function(v) trace_marks_set = v end)
+local trace_marks_get = false trackers.register("marks.get", function(v) trace_marks_get = v end)
+local trace_marks_all = false trackers.register("marks.detail", function(v) trace_marks_all = v end)
-local v_first = variables.first
-local v_last = variables.last
-local v_previous = variables.previous
-local v_next = variables.next
-local v_top = variables.top
-local v_bottom = variables.bottom
-local v_current = variables.current
-local v_default = variables.default
-local v_page = variables.page
-local v_all = variables.all
-local v_keep = variables.keep
+local report_marks = logs.reporter("structure","marks")
-local v_nocheck_suffix = ":" .. variables.nocheck
+local variables = interfaces.variables
-local v_first_nocheck = variables.first .. v_nocheck_suffix
-local v_last_nocheck = variables.last .. v_nocheck_suffix
-local v_previous_nocheck = variables.previous .. v_nocheck_suffix
-local v_next_nocheck = variables.next .. v_nocheck_suffix
-local v_top_nocheck = variables.top .. v_nocheck_suffix
-local v_bottom_nocheck = variables.bottom .. v_nocheck_suffix
+local v_first = variables.first
+local v_last = variables.last
+local v_previous = variables.previous
+local v_next = variables.next
+local v_top = variables.top
+local v_bottom = variables.bottom
+local v_current = variables.current
+local v_default = variables.default
+local v_page = variables.page
+local v_all = variables.all
+local v_keep = variables.keep
-local structures = structures
-local marks = structures.marks
-local lists = structures.lists
+local v_nocheck_suffix = ":" .. variables.nocheck
-local settings_to_array = utilities.parsers.settings_to_array
+local v_first_nocheck = variables.first .. v_nocheck_suffix
+local v_last_nocheck = variables.last .. v_nocheck_suffix
+local v_previous_nocheck = variables.previous .. v_nocheck_suffix
+local v_next_nocheck = variables.next .. v_nocheck_suffix
+local v_top_nocheck = variables.top .. v_nocheck_suffix
+local v_bottom_nocheck = variables.bottom .. v_nocheck_suffix
-local boxes_too = false -- at some point we can also tag boxes or use a zero char
+local structures = structures
+local marks = structures.marks
+local lists = structures.lists
+
+local settings_to_array = utilities.parsers.settings_to_array
+
+local boxes_too = false -- at some point we can also tag boxes or use a zero char
directives.register("marks.boxestoo", function(v) boxes_too = v end)
-marks.data = marks.data or allocate()
+local data = marks.data or allocate()
+marks.data = data
storage.register("structures/marks/data", marks.data, "structures.marks.data")
-local data = marks.data
local stack, topofstack = { }, 0
local ranges = {
@@ -116,9 +120,9 @@ end
-- identify range
local function sweep(head,first,last)
- for n in traverse(head) do
- local id = getid(n)
- if id == glyph_code then
+ for n, id, subtype in nextnode, head do
+ -- we need to handle empty heads so we test for latelua
+ if id == glyph_code or (id == whatsit_code and subtype == lateluawhatsit_code) then
local a = getattr(n,a_marks)
if not a then
-- next
@@ -433,7 +437,8 @@ local function resolve(name,first,last,strict,quitonfalse,notrace)
if trace_marks_get and not notrace then
report_marks("found chain [ % => T ]",fullchain)
end
- local chaindata, chainlength = { }, #fullchain
+ local chaindata = { }
+ local chainlength = #fullchain
for i=1,chainlength do
local cname = fullchain[i]
if data[cname].set > 0 then
@@ -509,7 +514,8 @@ local methods = { }
local function doresolve(name,rangename,swap,df,dl,strict)
local range = ranges[rangename] or ranges[v_page]
- local first, last = range.first, range.last
+ local first = range.first
+ local last = range.last
if trace_marks_get then
report_marks("action %a, name %a, range %a, swap %a, first %a, last %a, df %a, dl %a, strict %a",
"resolving",name,rangename,swap or false,first,last,df,dl,strict or false)
@@ -638,7 +644,10 @@ function marks.tracers.showtable()
context.tabulaterowbold("name","parent","chain","children","fullchain")
context.ML()
for k, v in table.sortedpairs(data) do
- local parent, chain, children, fullchain = v.parent or "", v.chain or "", v.children or { }, v.fullchain or { }
+ local parent = v.parent or ""
+ local chain = v.chain or ""
+ local children = v.children or { }
+ local fullchain = v.fullchain or { }
table.sort(children) -- in-place but harmless
context.tabulaterowtyp(k,parent,chain,concat(children," "),concat(fullchain," "))
end
@@ -647,28 +656,49 @@ end
-- pushing to context:
-local separator = context.nested.markingseparator
-local command = context.nested.markingcommand
-local ctxconcat = context.concat
-
-local function fetchonemark(name,range,method)
- context(command(name,fetched(name,range,method)))
-end
+-- local separator = context.nested.markingseparator
+-- local command = context.nested.markingcommand
+-- local ctxconcat = context.concat
+
+-- local function fetchonemark(name,range,method)
+-- context(command(name,fetched(name,range,method)))
+-- end
+
+-- local function fetchtwomarks(name,range)
+-- ctxconcat( {
+-- command(name,fetched(name,range,v_first)),
+-- command(name,fetched(name,range,v_last)),
+-- }, separator(name))
+-- end
+
+-- local function fetchallmarks(name,range)
+-- ctxconcat( {
+-- command(name,fetched(name,range,v_previous)),
+-- command(name,fetched(name,range,v_first)),
+-- command(name,fetched(name,range,v_last)),
+-- }, separator(name))
+-- end
+
+ local ctx_separator = context.markingseparator
+ local ctx_command = context.markingcommand
+
+ local function fetchonemark(name,range,method)
+ ctx_command(name,fetched(name,range,method))
+ end
-local function fetchtwomarks(name,range)
- ctxconcat( {
- command(name,fetched(name,range,v_first)),
- command(name,fetched(name,range,v_last)),
- }, separator(name))
-end
+ local function fetchtwomarks(name,range)
+ ctx_command(name,fetched(name,range,v_first))
+ ctx_separator(name)
+ ctx_command(name,fetched(name,range,v_last))
+ end
-local function fetchallmarks(name,range)
- ctxconcat( {
- command(name,fetched(name,range,v_previous)),
- command(name,fetched(name,range,v_first)),
- command(name,fetched(name,range,v_last)),
- }, separator(name))
-end
+ local function fetchallmarks(name,range)
+ ctx_command(name,fetched(name,range,v_previous))
+ ctx_separator(name)
+ ctx_command(name,fetched(name,range,v_first))
+ ctx_separator(name)
+ ctx_command(name,fetched(name,range,v_last))
+ end
function marks.fetch(name,range,method) -- chapter page first | chapter column:1 first
if trace_marks_get then
diff --git a/tex/context/base/mkiv/strc-mat.mkiv b/tex/context/base/mkiv/strc-mat.mkiv
index 775d2aca1..0b80a26cd 100644
--- a/tex/context/base/mkiv/strc-mat.mkiv
+++ b/tex/context/base/mkiv/strc-mat.mkiv
@@ -208,9 +208,9 @@
\c!reference=#1,\c!title=\namedformulaentry,\c!bookmark=]%
[#2]%
\glet\namedformulaentry\empty % \relax
- \globallet#3\m_strc_counters_last_registered_index
- \globallet#4\m_strc_counters_last_registered_synchronize
- \globallet#5\m_strc_counters_last_registered_attribute}
+ \glet#3\m_strc_counters_last_registered_index
+ \glet#4\m_strc_counters_last_registered_synchronize
+ \glet#5\m_strc_counters_last_registered_attribute}
% modes: 0=unset, 1=forced, 2=none, 3=reference
@@ -880,6 +880,9 @@
\par
\fi
\bgroup % HERE
+ \iftrialtypesetting\else
+ \global\advance\c_strc_formulas_n\plusone
+ \fi
\def\currentformula{#1}%
\strc_math_set_split
\dostarttaggedchained\t!formula\currentformula\??formula
@@ -896,7 +899,7 @@
{\edef\p_option{\formulaparameter\c!option}%
\edef\p_option{\ifx\p_option\empty\else\p_option,\fi#2}}%
\else
- \edef\p_option{\formulaparameter\c!option}
+ \edef\p_option{\formulaparameter\c!option}%
\fi
\ifx\p_option\empty \else
\rawprocesscommacommand[\p_option]\strc_formulas_option
@@ -922,10 +925,15 @@
% tagging of formulanumbers is not ok (we get two display maths blobs)
+\newcount\c_strc_formulas_n
+
+\ifdefined\dotagregisterformula \else \let\dotagregisterformula\gobbleoneargument \fi
+
\unexpanded\def\strc_formulas_stop_formula
{\strc_formulas_place_number % in case it hasn't happened yet
\strc_formulas_flush_number % in case we are in native mode
\dostarttagged\t!formulacontent\empty
+ \dotagregisterformula\c_strc_formulas_n
\csname\e!stop\formulaparameter\c!alternative\v!formula\endcsname
\dostoptagged
\dostoptagged
diff --git a/tex/context/base/mkiv/strc-not.lua b/tex/context/base/mkiv/strc-not.lua
index bb9d64beb..b2c8106e1 100644
--- a/tex/context/base/mkiv/strc-not.lua
+++ b/tex/context/base/mkiv/strc-not.lua
@@ -247,15 +247,38 @@ end
notes.internal = internal
notes.ordered = ordered
+-- local function onsamepageasprevious(tag)
+-- local same = false
+-- local n = getn(tag,n)
+-- local current = get(tag,n)
+-- local previous = get(tag,n-1)
+-- if current and previous then
+-- local cr = current.references
+-- local pr = previous.references
+-- same = cr and pr and cr.realpage == pr.realpage
+-- end
+-- return same and true or false
+-- end
+
local function onsamepageasprevious(tag)
- local same = false
- local n = getn(tag,n)
- local current, previous = get(tag,n), get(tag,n-1)
- if current and previous then
- local cr, pr = current.references, previous.references
- same = cr and pr and cr.realpage == pr.realpage
+ local n = getn(tag,n)
+ local current = get(tag,n)
+ if not current then
+ return false
+ end
+ local cr = current.references
+ if not cr then
+ return false
+ end
+ local previous = get(tag,n-1)
+ if not previous then
+ return false
+ end
+ local pr = previous.references
+ if not pr then
+ return false
end
- return same and true or false
+ return cr.realpage == pr.realpage
end
notes.doifonsamepageasprevious = onsamepageasprevious
@@ -471,7 +494,7 @@ local texsetglue = tex.setglue
local function check_spacing(n,i)
local gn, pn, mn = texgetglue(n)
local gi, pi, mi = texgetglue(i > 1 and "s_strc_notes_inbetween" or "s_strc_notes_before")
- local gt, pt, mt = gn+gi, pn+pi, mn+mi
+ local gt, pt, mt = gn + gi, pn + pi, mn + mi
if trace_insert then
report_insert("%s %i: %p plus %p minus %p","always ",n,gn,pn,mn)
report_insert("%s %i: %p plus %p minus %p",i > 1 and "inbetween" or "before ",n,gi,pi,mi)
diff --git a/tex/context/base/mkiv/strc-not.mkvi b/tex/context/base/mkiv/strc-not.mkvi
index 8952f0e9c..3ce01ef34 100644
--- a/tex/context/base/mkiv/strc-not.mkvi
+++ b/tex/context/base/mkiv/strc-not.mkvi
@@ -456,7 +456,7 @@
\edef\currentnotenumber{\clf_storenote{\currentnote}\currentconstructionlistentry}%
\settrue\processingnote
\ifconditional\c_strc_notes_skip
- \globallet\lastnotesymbol\strc_notes_inject_symbol_nop
+ \glet\lastnotesymbol\strc_notes_inject_symbol_nop
\else
\iftypesettinglines % otherwise problems with \type <crlf> {xxx}
\ignorelines % makes footnotes work in \startlines ... \stoplines
@@ -465,7 +465,7 @@
\strc_notes_inject_symbol_yes
\else
\unskip\unskip
- \globallet\lastnotesymbol\strc_notes_inject_symbol_yes
+ \glet\lastnotesymbol\strc_notes_inject_symbol_yes
\fi
\fi
\ifconditional\postponingnotes % todo: per note class
@@ -734,7 +734,7 @@
\dostoptagged
\egroup
\endgroup
- \globallet\lastnotesymbol\relax}
+ \glet\lastnotesymbol\relax}
\unexpanded\def\strc_notes_inject_dummy % temp hack
{\removeunwantedspaces
@@ -745,7 +745,7 @@
\fi
\nobreak
\hpack to .5\emwidth{}%
- \globallet\lastnotesymbol\relax}
+ \glet\lastnotesymbol\relax}
\unexpanded\def\strc_notes_inject_separator % patch by WS due to request on list
{\edef\p_textseparator{\noteparameter\c!textseparator}%
@@ -1057,18 +1057,6 @@
\newskip \s_strc_notes_distance % we need to implement stretch
\newcount\c_strc_notes_columns
-% \def\strc_notes_set_distance
-% {\begingroup
-% \setbox\scratchbox\vbox % no reuse as it can mirror
-% {\forgetall
-% \restoreglobalbodyfont % really needed
-% \dontcomplain
-% \noteparameter\c!before
-% \placenoterule
-% \noteparameter\c!after}%
-% \expandafter\endgroup\expandafter
-% \s_strc_notes_distance\the\htdp\scratchbox\relax} % also dp now
-
\newskip \s_strc_notes_before
\newskip \s_strc_notes_inbetween
\newconditional\c_strc_notes_first_flushed
@@ -1382,19 +1370,22 @@
\fi}
\appendtoks
- \strc_notes_set_penalties
- \forgetall % again
- \strc_notes_set_bodyfont
- \redoconvertfont % to undo \undo calls in in headings etc
- \splittopskip\strutht % not actually needed here
- \splitmaxdepth\strutdp % not actually needed here
- % not:
-% \leftmargindistance \noteparameter\c!margindistance
-% \rightmargindistance\leftmargindistance
-% \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ?
-% \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ?
-% \fi
- %
+ \strc_notes_set_penalties
+ \forgetall % again
+ \strc_notes_set_bodyfont
+ \redoconvertfont % to undo \undo calls in in headings etc
+ \splittopskip\strutht % not actually needed here
+ \splitmaxdepth\strutdp % not actually needed here
+ %
+ % not:
+ %
+ % \leftmargindistance \noteparameter\c!margindistance
+ % \rightmargindistance\leftmargindistance
+ % \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ?
+ % \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ?
+ % \fi
+ %
+ \pickupattributes
\to \everyinsidenoteinsert
% maybe but better use [scope=local] here
@@ -1551,7 +1542,7 @@
\unexpanded\def\postponenotes
{\ifconditional\postponingnotes\else
\global\settrue\postponingnotes
- \global\let\flushnotes\doflushnotes
+ \glet\flushnotes\doflushnotes
\clf_postponenotes
\fi}
@@ -1560,7 +1551,7 @@
\unexpanded\def\startpostponingnotes % experimental, page-mix
{\ifconditional\postponingnotes\else
\global\settrue\postponingnotes
- %\global\let\flushnotes\doflushnotes
+ %\glet\flushnotes\doflushnotes
\clf_postponenotes
\fi}
@@ -1581,7 +1572,7 @@
\clf_flushpostponednotes% this also resets the states !
\global\setfalse\postponednote
\global\setfalse\postponingnotes
- \global\let\flushnotes\relax
+ \glet\flushnotes\relax
\endgroup
\fi}
diff --git a/tex/context/base/mkiv/strc-num.lua b/tex/context/base/mkiv/strc-num.lua
index e1a133f4a..25e575a56 100644
--- a/tex/context/base/mkiv/strc-num.lua
+++ b/tex/context/base/mkiv/strc-num.lua
@@ -273,7 +273,7 @@ end
function counters.compact(name,level,onlynumbers)
local cd = counterdata[name]
if cd then
- local data = cd.data
+ local data = cd.data
local compact = { }
for i=1,level or #data do
local d = data[i]
@@ -541,22 +541,26 @@ function counters.converted(name,spec) -- name can be number and reference to st
local cd
if type(name) == "number" then
cd = specials.retrieve("counter",name)
- cd = cd and cd.counter
+ if cd then
+ cd = cd.counter
+ end
else
cd = counterdata[name]
end
if cd then
- local spec = spec or { }
- local numbers, ownnumbers = { }, { }
- local reverse = spec.order == v_reverse
- local kind = spec.type or "number"
- local data = cd.data
+ local spec = spec or { }
+ local numbers = { }
+ local ownnumbers = { }
+ local reverse = spec.order == v_reverse
+ local kind = spec.type or "number"
+ local data = cd.data
for k=1,#data do
local v = data[k]
-- somewhat messy, what if subnr? only last must honour kind?
local vn
if v.own then
- numbers[k], ownnumbers[k] = v.number, v.own
+ numbers[k] = v.number
+ ownnumbers[k] = v.own
else
if kind == v_first then
vn = v.first
@@ -577,13 +581,14 @@ function counters.converted(name,spec) -- name can be number and reference to st
end
end
end
- numbers[k], ownnumbers[k] = vn or v.number, nil
+ numbers[k] = vn or v.number
+ ownnumbers[k] = nil
end
end
- cd.numbers = numbers
+ cd.numbers = numbers
cd.ownnumbers = ownnumbers
sections.typesetnumber(cd,'number',spec)
- cd.numbers = nil
+ cd.numbers = nil
cd.ownnumbers = nil
end
end
diff --git a/tex/context/base/mkiv/strc-num.mkiv b/tex/context/base/mkiv/strc-num.mkiv
index be35e7671..747df29a5 100644
--- a/tex/context/base/mkiv/strc-num.mkiv
+++ b/tex/context/base/mkiv/strc-num.mkiv
@@ -578,9 +578,9 @@
\xdef\currentstructurecomponentlist {#2\c!list}%
\xmlstopraw
\ifx\currentstructurecomponentlist\empty
- \globallet\currentstructurecomponentlist\currentstructurecomponenttitle
+ \glet\currentstructurecomponentlist\currentstructurecomponenttitle
\fi
- \globallet\currentstructurecomponentcoding\s!xml
+ \glet\currentstructurecomponentcoding\s!xml
\else
\ifx\currentstructurecomponentexpansion\v!yes
\xdef\currentstructurecomponenttitle {#2\c!title}%
@@ -600,9 +600,9 @@
\fi \fi
\fi
\ifx\currentstructurecomponentlist\empty
- \globallet\currentstructurecomponentlist\currentstructurecomponenttitle
+ \glet\currentstructurecomponentlist\currentstructurecomponenttitle
\fi
- \globallet\currentstructurecomponentcoding\s!tex
+ \glet\currentstructurecomponentcoding\s!tex
\fi
%
\setnextinternalreference
@@ -669,11 +669,9 @@
%}
\relax
\xdef\m_strc_counters_last_registered_index{\the\scratchcounter}%
- \clf_setinternalreference
- internal \locationcount
- \relax
- \xdef\m_strc_counters_last_registered_attribute {\the\lastdestinationattribute}%
- \xdef\m_strc_counters_last_registered_synchronize{\strc_lists_inject_enhance{\m_strc_counters_last_registered_index}{\the\locationcount}}}
+ \setstructurecomponentsynchronization\m_strc_counters_last_registered_index
+ \glet\m_strc_counters_last_registered_attribute \currentstructurecomponentattribute
+ \glet\m_strc_counters_last_registered_synchronize\currentstructurecomponentsynchronize}
\let\m_strc_counters_last_registered_index \relax
\let\m_strc_counters_last_registered_attribute \relax
diff --git a/tex/context/base/mkiv/strc-pag.lua b/tex/context/base/mkiv/strc-pag.lua
index dcd35fc20..ee1b245b9 100644
--- a/tex/context/base/mkiv/strc-pag.lua
+++ b/tex/context/base/mkiv/strc-pag.lua
@@ -113,8 +113,9 @@ end
-- end
function pages.number(realdata,pagespec)
- local userpage, block = realdata.number, realdata.block or "" -- sections.currentblock()
- local numberspec = realdata.numberdata
+ local userpage = realdata.number
+ local block = realdata.block or "" -- sections.currentblock()
+ local numberspec = realdata.numberdata
local conversionset = (pagespec and pagespec.conversionset ~= "" and pagespec.conversionset) or (numberspec and numberspec.conversionset ~= "" and numberspec.conversionset) or ""
local conversion = (pagespec and pagespec.conversion ~= "" and pagespec.conversion ) or (numberspec and numberspec.conversion ~= "" and numberspec.conversion ) or ""
local starter = (pagespec and pagespec.starter ~= "" and pagespec.starter ) or (numberspec and numberspec.starter ~= "" and numberspec.starter ) or ""
@@ -212,9 +213,11 @@ end
function helpers.prefixlastpage(data,prefixspec,pagespec)
if data then
- local r = data.references
- local ls, lr = r.section, r.realpage
- r.section, r.realpage = r.lastsection or r.section, r.lastrealpage or r.realpage
+ local r = data.references
+ local ls = r.section
+ local lr = r.realpage
+ r.section = r.lastsection or r.section
+ r.realpage = r.lastrealpage or r.realpage
helpers.prefixpage(data,prefixspec,pagespec)
r.section, r.realpage = ls, lr
end
@@ -227,7 +230,8 @@ function helpers.analyze(entry,specification)
if not entry then
return false, false, "no entry"
end
- local yes, no = variables.yes, variables.no
+ local yes = variables.yes
+ local no = variables.no
-- section data
local references = entry.references
if not references then
diff --git a/tex/context/base/mkiv/strc-pag.mkiv b/tex/context/base/mkiv/strc-pag.mkiv
index d56f0de54..01361e2c5 100644
--- a/tex/context/base/mkiv/strc-pag.mkiv
+++ b/tex/context/base/mkiv/strc-pag.mkiv
@@ -152,7 +152,7 @@
\setupsubpagenumber
[\c!way=\v!by\v!part,
- \c!state=\v!stop]
+ \c!state=\v!start] % was stop but start looks better in logging
% Counters
@@ -263,7 +263,7 @@
\def\currentpage{\the\realpageno}% rather useless
\appendtoks
- \ifnum\realpageno>\lastpage \globallet\lastpage\lastrealpage \fi
+ \ifnum\realpageno>\lastpage \glet\lastpage\lastrealpage \fi
\to \everyinitializepagecounters
% States:
@@ -309,6 +309,8 @@
% some day ifsinglesided and ifdoublesided will become obsolete
+\newtoks\everysidedswitch
+
\appendtoks
\singlesidedfalse \setfalse\layoutisdoublesided
\doublesidedfalse \setfalse\layoutissinglesided
@@ -317,13 +319,7 @@
\processallactionsinset[\directpagenumberingparameter\c!alternative]
[ \v!singlesided=>\setsystemmode\v!singlesided\singlesidedtrue\settrue\layoutissinglesided,
\v!doublesided=>\setsystemmode\v!doublesided\doublesidedtrue\settrue\layoutisdoublesided]%
- \ifdefined\trackingmarginnotestrue
- \ifdoublesided
- \trackingmarginnotestrue
- \else
- \trackingmarginnotesfalse
- \fi
- \fi
+ \the\everysidedswitch
\pageduplexmode
\ifsinglesided
\ifdoublesided\plustwo\else\zerocount\fi
@@ -334,6 +330,16 @@
\strc_pagenumbers_set_location
\to \everysetuppagenumbering
+\appendtoks
+ \ifdefined\trackingmarginnotestrue
+ \ifdoublesided
+ \trackingmarginnotestrue
+ \else
+ \trackingmarginnotesfalse
+ \fi
+ \fi
+\to \everysidedswitch
+
\ifdefined \page_backgrounds_recalculate \else
\let\page_backgrounds_recalculate\relax
\fi
@@ -401,11 +407,10 @@
\unexpanded\def\strc_pagenumbers_check_state_change#1#2%
{\edef\m_strc_pagenumbers_state_new{\namedcounterparameter#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}%
+ #2\ifx\m_strc_pagenumbers_state_new\v!start\plustwo\else\zerocount\fi
\fi}
+
\appendtoks % todo: set state: none, start, stop, reset
\strc_pagenumbers_check_state_change\s!realpage\c_strc_pagenumbers_state_realpage
\to \everysetuprealpagenumber
diff --git a/tex/context/base/mkiv/strc-ref.lua b/tex/context/base/mkiv/strc-ref.lua
index f20d93161..e01bacaac 100644
--- a/tex/context/base/mkiv/strc-ref.lua
+++ b/tex/context/base/mkiv/strc-ref.lua
@@ -52,6 +52,8 @@ local context = context
local commands = commands
local implement = interfaces.implement
+local ctx_latelua = context.latelua
+
local texgetcount = tex.getcount
local texsetcount = tex.setcount
local texconditionals = tex.conditionals
@@ -72,6 +74,7 @@ local lists = structures.lists
local counters = structures.counters
local jobpositions = job.positions
+local getpos = jobpositions.getpos
-- some might become local
@@ -137,6 +140,7 @@ storage.register("structures/references/defined", references.defined, "structure
local initializers = { }
local finalizers = { }
+local somefound = false -- so we don't report missing when we have a fresh start
function references.registerinitializer(func) -- we could use a token register instead
initializers[#initializers+1] = func
@@ -162,6 +166,7 @@ local function initializer() -- can we use a tobesaved as metatable for collecte
end
end
end
+ somefound = next(collected)
end
local function finalizer()
@@ -370,6 +375,8 @@ implement {
arguments = "2 strings",
}
+local reported = setmetatableindex("table")
+
function references.set(data)
local references = data.references
local reference = references.reference
@@ -388,16 +395,23 @@ function references.set(data)
if ref == "" then
-- skip
elseif check_duplicates and pd[ref] then
- if prefix and prefix ~= "" then
- report_references("redundant reference %a in namespace %a",ref,prefix)
- else
- report_references("redundant reference %a",ref)
+ if not prefix then
+ prefix = ""
+ end
+ if not reported[prefix][ref] then
+ if prefix ~= "" then
+ report_references("redundant reference %a in namespace %a",ref,prefix)
+ else
+ report_references("redundant reference %a",ref)
+ end
+ reported[prefix][ref] = true
end
else
n = n + 1
pd[ref] = data
local r = data.references
ctx_dofinishreference(prefix or "",ref or "",r and r.internal or 0)
+ -- ctx_latelua(function() structures.references.enhance(prefix or ref,ref or "") end)
end
end
process_settings(reference,action)
@@ -411,8 +425,6 @@ end
-- end
-- end
-local getpos = function() getpos = backends.codeinjections.getpos return getpos () end
-
local function synchronizepage(reference) -- non public helper
reference.realpage = texgetcount("realpageno")
if jobpositions.used then
@@ -422,17 +434,30 @@ end
references.synchronizepage = synchronizepage
-function references.enhance(prefix,tag)
- local l = tobesaved[prefix][tag]
+local function enhancereference(specification)
+ local l = tobesaved[specification.prefix][specification.tag]
if l then
synchronizepage(l.references)
end
end
+references.enhance = enhancereference
+
+-- implement {
+-- name = "enhancereference",
+-- arguments = "2 strings",
+-- actions = function(prefix,tag)
+-- enhancereference { prefix = prefix, tag = tag }
+-- end,
+-- }
+
implement {
- name = "enhancereference",
- actions = references.enhance,
+ name = "deferredenhancereference",
arguments = "2 strings",
+ protected = true,
+ actions = function(prefix,tag)
+ ctx_latelua { action = enhancereference, prefix = prefix, tag = tag }
+ end,
}
-- -- -- related to strc-ini.lua -- -- --
@@ -1004,9 +1029,9 @@ local function loadexternalreferences(name,utilitydata)
local pages = struc.pages.collected -- pagenumber data
-- a bit weird one, as we don't have the externals in the collected
for prefix, set in next, external do
-if prefix == "" then
- prefix = name -- this can clash!
-end
+ if prefix == "" then
+ prefix = name -- this can clash!
+ end
for reference, data in next, set do
if trace_importing then
report_importing("registering %a reference, kind %a, name %a, prefix %a, reference %a",
@@ -1034,9 +1059,9 @@ end
if kind and realpage then
references.pagedata = pages[realpage]
local prefix = references.prefix or ""
-if prefix == "" then
- prefix = name -- this can clash!
-end
+ if prefix == "" then
+ prefix = name -- this can clash!
+ end
local target = external[prefix]
if not target then
target = { }
@@ -1468,7 +1493,7 @@ local function identify_inner(set,var,prefix,collected,derived)
end
end
-- we now ignore the split prefix and treat the whole inner as a potential
- -- referenice into the global list
+ -- reference into the global list
local i = collected[prefix]
if i then
i = i[inner]
@@ -1524,6 +1549,17 @@ local function identify_outer(set,var,i)
end
return v
end
+-- weird too (we really need to check how this table is build
+ local v = identify_inner(set,var,var.outer,external)
+ if v then
+ v.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,v,i,"2c")
+ end
+ return v
+ end
+--
-- somewhat rubish: we use outer as first step in the externals table so it makes no
-- sense to have it as prefix so the next could be an option
local external = external[""]
@@ -1798,8 +1834,7 @@ local nofidentified = 0
local function identify(prefix,reference)
if not reference then
- prefix = ""
- reference = prefix
+ prefix, reference = "", prefix
end
local set = resolve(prefix,reference)
local bug = false
@@ -1847,7 +1882,9 @@ function references.valid(prefix,reference,specification)
local str = f_valid(prefix,reference)
local u = unknowns[str]
if not u then
- interfaces.showmessage("references",1,str) -- 1 = unknown, 4 = illegal
+ if somefound then
+ interfaces.showmessage("references",1,str) -- 1 = unknown, 4 = illegal
+ end
unknowns[str] = 1
nofunknowns = nofunknowns + 1
else
@@ -1964,13 +2001,14 @@ local function setinternalreference(specification)
local internal = specification.internal
local destination = unsetvalue
if innermethod == v_auto or innermethod == v_name then
- local t, tn = { }, 0 -- maybe add to current (now only used for tracing)
+ local t = { } -- maybe add to current (now only used for tracing)
+ local tn = 0
local reference = specification.reference
local view = specification.view
if reference then
local prefix = specification.prefix
if prefix and prefix ~= "" then
- prefix = prefix .. ":" -- watch out, : here
+ local prefix = prefix .. ":" -- watch out, : here
local function action(ref)
tn = tn + 1
t[tn] = prefix .. ref
@@ -1987,7 +2025,7 @@ local function setinternalreference(specification)
-- ugly .. later we decide to ignore it when we have a real one
-- but for testing we might want to see them all
if internal then
- if innermethod ~= v_name then -- so page and auto
+ if innermethod ~= v_name then -- innermethod == v_auto
-- we don't want too many #1 #2 #3 etc
tn = tn + 1
t[tn] = internal -- when number it's internal
@@ -2064,7 +2102,7 @@ function references.setandgetattribute(data) -- maybe do internal automatically
local done = references.set(data) -- we had kind i.e .item -> full
if done then
attr = setinternalreference {
- prefix = prefix,
+ prefix = rdat.prefix,
reference = rdat.reference,
internal = rdat.internal,
view = rdat.view
@@ -2285,7 +2323,8 @@ genericfilters.default = genericfilters.text
function genericfilters.page(data,prefixspec,pagespec)
local pagedata = data.pagedata
if pagedata then
- local number, conversion = pagedata.number, pagedata.conversion
+ local number = pagedata.number
+ local conversion = pagedata.conversion
if not number then
-- error
elseif conversion then
@@ -2527,10 +2566,19 @@ local function referencepagestate(position,detail,spread)
if not actions then
return 0
else
- if not actions.pagestate then
+ local pagestate = actions.pagestate
+ for i=1,#actions do
+ local a = actions[i]
+ if a.outer then
+ pagestate = 0
+ actions.pagestate = pagestate
+ break
+ end
+ end
+ if not pagestate then
references.analyze(actions,position,spread) -- delayed unless explicitly asked for
+ pagestate = actions.pagestate
end
- local pagestate = actions.pagestate
if detail then
return pagestate
elseif pagestate == 4 then
diff --git a/tex/context/base/mkiv/strc-ref.mkvi b/tex/context/base/mkiv/strc-ref.mkvi
index d0752407c..c7f204815 100644
--- a/tex/context/base/mkiv/strc-ref.mkvi
+++ b/tex/context/base/mkiv/strc-ref.mkvi
@@ -29,7 +29,7 @@
\registerctxluafile{strc-rsc}{}
\registerctxluafile{strc-ref}{}
-\registerctxluafile{node-ref}{}
+\registerctxluafile{node-ref}{optimize}
\unprotect
@@ -45,19 +45,18 @@
% \definespecial\dosetexecuteJScode
% ...
-%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 This module deals with referencing. In \CONTEXT\ referencing is one of the core
+%D features, although at a first glance probably nobody will notice. This is good,
+%D because referencing should be as hidden as possible.
%D
-%D Before we start implementing functionality we provide a way to set
-%D up this mechanism.
+%D Before we start implementing functionality we provide a way to set up this
+%D mechanism.
%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.
+%D In interactive documents verbose references don't always make sense (what is a
+%D page number in an unnumbered document). By setting the \type{interaction}
+%D variable, one can influences the way interactive references are set.
\let\referenceprefix\empty
@@ -122,20 +121,19 @@
\dosetdirectpagereference\m_strc_references_asked
\fi}
-%D Actually there is not much difference between a text and a
-%D full reference, but it's the concept that counts. The low
-%D level implementation is:
+%D Actually there is not much difference between a text and a full reference, but
+%D it's the concept that counts. The low level implementation is:
\newcount\lastreferenceattribute
\newcount\lastdestinationattribute
\def\strc_references_finish#prefix#reference#internal%
- {\normalexpanded{\ctxlatecommand{enhancereference("#prefix","#reference")}}}
+ {\normalexpanded{\clf_deferredenhancereference{#prefix}{#reference}}}
\let\dofinishreference\strc_references_finish % used at lua end
-% This is somewhat tricky: we want to keep the reference with the following word but
-% that word should also hyphenate. We need to find a better way.
+%D This is somewhat tricky: we want to keep the reference with the following word but
+%D that word should also hyphenate. We need to find a better way.
% 0 = nothing
% 1 = bind to following word
@@ -167,6 +165,32 @@
\unhbox\b_strc_destination_nodes
\fi}
+\def\strc_references_placeholder
+ {\ifx\dotaggedplaceholder\empty\else
+ \attribute\destinationattribute\lastdestinationattribute
+ \dotaggedplaceholder
+ \fi}
+
+\unexpanded\def\strc_references_destination_point_yes
+ {\strc_references_inject_before % new
+ \dostarttagged\t!reference\empty
+ \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup
+ \strc_references_flush_destination_nodes
+ \strc_references_placeholder
+ \egroup
+ \dostoptagged
+ \strc_references_inject_after}
+
+\unexpanded\def\strc_references_destination_point_nop
+ {\strc_references_inject_before % new
+ \dostarttagged\t!reference\empty
+ \dontleavehmode\hbox \bgroup
+ \strc_references_flush_destination_nodes
+ \strc_references_placeholder
+ \egroup
+ \dostoptagged
+ \strc_references_inject_after}
+
\unexpanded\def\strc_references_start_destination_nodes % messy but we need the delay
{\setbox\b_strc_destination_nodes\hbox\bgroup} % also sets lastdestinationattribute
@@ -188,14 +212,14 @@
\xmlstartraw
\xdef\currentreferencedata{#text}% data, no text else conflict
\xmlstopraw
- \globallet\currentreferencecoding\s!xml
+ \glet\currentreferencecoding\s!xml
\else
\ifx\currentreferenceexpansion\v!yes
\xdef\currentreferencedata{#text}%
\else
\xdef\currentreferencedata{\detokenize{#text}}%
\fi
- \globallet\currentreferencecoding\s!tex
+ \glet\currentreferencecoding\s!tex
\fi
% beware, the structures.references.set writes a
\setnextinternalreference
@@ -240,17 +264,9 @@
\xdef\currentdestinationattribute{\number\lastdestinationattribute}%
% will become an option:
\ifnum\lastdestinationattribute>\zerocount
- \strc_references_inject_before % new
- \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup
- \strc_references_flush_destination_nodes
- \egroup
- \strc_references_inject_after % new
+ \strc_references_destination_point_yes
\else\ifvoid\b_strc_destination_nodes\else
- \strc_references_inject_before % new
- \dontleavehmode\hbox \bgroup
- \strc_references_flush_destination_nodes
- \egroup
- \strc_references_inject_after % new
+ \strc_references_destination_point_nop
\fi\fi}
\def\strc_references_set_page_only_destination_attribute#labels% could in fact be fully expandable
@@ -324,17 +340,9 @@
\xdef\currentdestinationattribute{\number\lastdestinationattribute}%
% will become an option:
\ifnum\lastdestinationattribute>\zerocount
- \strc_references_inject_before % new
- \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup
- \strc_references_flush_destination_nodes
- \egroup
- \strc_references_inject_after % new
+ \strc_references_destination_point_yes
\else\ifvoid\b_strc_destination_nodes\else
- \strc_references_inject_before % new
- \dontleavehmode\hbox \bgroup
- \strc_references_flush_destination_nodes
- \egroup
- \strc_references_inject_after % new
+ \strc_references_destination_point_nop
\fi\fi}
\unexpanded\def\strc_references_direct_full
@@ -479,10 +487,10 @@
{\scratchwidth \wd\nextbox
\scratchheight\ht\nextbox
\scratchdepth \dp\nextbox
- \setbox\nextbox\hbox % \hpack ?
+ \setbox\nextbox\hpack
{\framed[\c!frame=\v!off,#2]{\box\nextbox}}%
\strc_references_set_simple_reference{#1}%
- \setbox\nextbox\hbox attr \destinationattribute \currentdestinationattribute % \hpack ?
+ \setbox\nextbox\hpack attr \destinationattribute \currentdestinationattribute % \hpack ?
{\strc_references_flush_destination_nodes
\box\nextbox}%
\setbox\nextbox\hpack{\box\nextbox}%
@@ -494,7 +502,7 @@
\def\strc_references_content_nop_finish#1#2%
{\strc_references_set_simple_reference{#1}%
- \hbox attr \destinationattribute \currentdestinationattribute % \hpack ?
+ \hpack attr \destinationattribute \currentdestinationattribute % \hpack ?
{\strc_references_flush_destination_nodes
\box\nextbox}%
\egroup}
@@ -502,34 +510,31 @@
%D \macros
%D {everyreference}
%D
-%D For rather tricky purposes, one can assign sanitizing
-%D macros to \type{\everyreference} (no longer that relevant).
+%D For rather tricky purposes, one can assign sanitizing macros to \type
+%D {\everyreference} (no longer that relevant).
\newevery \everyreference \relax
-%D This is really needed, since for instance Polish has a
-%D different alphabet and needs accented entries in registers.
+%D This is really needed, since for instance Polish has a different alphabet and
+%D needs accented entries in registers.
\appendtoks
\cleanupfeatures
\to \everyreference
-%D We did not yet discuss prefixing. Especially in interactive
-%D documents, it's not always easy to keep track of duplicate
-%D references. The prefix mechanism, which we will describe
-%D later on, solves this problem. By (automatically) adding a
-%D prefix one keeps references local, but the global ones in
-%D view. To enable this feature, we explictly split the prefix
-%D from the reference.
+%D We did not yet discuss prefixing. Especially in interactive documents, it's not
+%D always easy to keep track of duplicate references. The prefix mechanism, which we
+%D will describe later on, solves this problem. By (automatically) adding a prefix
+%D one keeps references local, but the global ones in view. To enable this feature,
+%D we explictly split the prefix from the reference.
\let\referenceprefix\empty
-%D For a long time the only way to access an external file was
-%D to use the file prefix (\type {somefile::}. However, when
-%D you split up a document, redefining the references may be
-%D such a pain, that another approach is feasible. By setting
-%D the \type {autofile} variable to \type {yes} or \type
-%D {page}, you can access the reference directly.
+%D For a long time the only way to access an external file was to use the file
+%D prefix (\type {somefile::}. However, when you split up a document, redefining the
+%D references may be such a pain, that another approach is feasible. By setting the
+%D \type {autofile} variable to \type {yes} or \type {page}, you can access the
+%D reference directly.
%D
%D \starttabulate[||||]
%D \NC filename::tag \NC page(filename::pnum) \NC tag \NC\NR
@@ -540,9 +545,9 @@
\unexpanded\def\usereferences[#filename]{} % obsolete
-%D As mentioned we will also use the cross reference mechanism
-%D for navigational purposes. The main reason for this is that
-%D we want to treat both categories alike:
+%D As mentioned we will also use the cross reference mechanism for navigational
+%D purposes. The main reason for this is that we want to treat both categories
+%D alike:
%D
%D \starttyping
%D \goto{go back}[PreviousJump]
@@ -553,15 +558,13 @@
%D \type{colofon page} reference is, apart from hyperlinking, a
%D rather normal reference.
%D
-%D We already saw that cross refences are written to and read
-%D from a file. The pure navigational ones don't need to be
-%D written to file, but both for fast processing and
-%D transparant integration, they are saved internally as a sort
-%D of reference. We can easily distinguish such system
-%D references from real cross reference ones by their tag.
+%D We already saw that cross refences are written to and read from a file. The pure
+%D navigational ones don't need to be written to file, but both for fast processing
+%D and transparant integration, they are saved internally as a sort of reference. We
+%D can easily distinguish such system references from real cross reference ones by
+%D their tag.
%D
-%D We also use the odd/even characteristic to determine the
-%D page state.
+%D We also use the odd/even characteristic to determine the page state.
\let\currentrealreference \empty
\let\currentpagereference \empty
@@ -576,11 +579,10 @@
%
% 0 = no page ref, 1=same page, 2=before, 3=after
-%D Cross references appear as numbers (figure~1.1, chapter~2)
-%D or pagenumbers (page~2, page 3--2), and are called with
-%D \type{\in} and \type{\at}. In interactive documents we also
-%D have \type{\goto}, \type{\button} and alike. These are more
-%D versatile and look like:
+%D Cross references appear as numbers (figure~1.1, chapter~2) or pagenumbers
+%D (page~2, page 3--2), and are called with \type {\in} and \type {\at}. In
+%D interactive documents we also have \type {\goto}, \type {\button} and alike.
+%D These are more versatile and look like:
%D
%D \starttyping
%D \goto[reference]
@@ -592,23 +594,19 @@
%D \goto[action{argument}]
%D \stoptyping
%D
-%D The first one is a normal reference, the second and third
-%D are references to a file or \URL. The brace delimited
-%D references for instance refer to a \JAVASCRIPT. The last
-%D example shows that we can pass arguments to the actions.
+%D The first one is a normal reference, the second and third are references to a
+%D file or \URL. The brace delimited references for instance refer to a \JAVASCRIPT.
+%D The last example shows that we can pass arguments to the actions.
%D
-%D Now we've come to the testing step. As we can see below,
-%D this macro does bit more than testing: it also resolves
-%D the reference. This means that whenever we test for the
-%D existance of a reference at an outer level, we have all the
-%D relevant properties of that reference avaliable inside the
-%D true branche~(\type{#2}).
+%D Now we've come to the testing step. As we can see below, this macro does bit more
+%D than testing: it also resolves the reference. This means that whenever we test
+%D for the existance of a reference at an outer level, we have all the relevant
+%D properties of that reference avaliable inside the true branche~(\type {#2}).
%D
-%D The prefix has to do with localizing references. When a
-%D prefix is set, looking for a reference comes to looking for
-%D the prefixed one, and when not found, looking for the non
-%D prefixed one. Consider for instance the prefix set to
-%D \type{sidetrack}.
+%D The prefix has to do with localizing references. When a prefix is set, looking
+%D for a reference comes to looking for the prefixed one, and when not found,
+%D looking for the non prefixed one. Consider for instance the prefix set to \type
+%D {sidetrack}.
%D
%D \starttyping
%D \pagereference[important]
@@ -625,17 +623,15 @@
%D ...{sidetrack}{important}...
%D \stoptyping
%D
-%D Now when we call for \type{unimportant}, we will indeed get
-%D the pagenumber associated to this reference. But when we
-%D call for \type{important}, while the prefix is still set, we
-%D will get the pagenumber bound to the prefixed one.
+%D Now when we call for \type{unimportant}, we will indeed get the pagenumber
+%D associated to this reference. But when we call for \type{important}, while the
+%D prefix is still set, we will get the pagenumber bound to the prefixed one.
%D
%D {\em Some day, when processing time and memory are no longer
%D performance factors, we will introduce multi||level
%D prefixes.}
%D
-%D Before we start analyzing, I introduce a general
-%D definition macro. Consider:
+%D Before we start analyzing, I introduce a general definition macro. Consider:
%D
%D \starttyping
%D \goto{do}[JS(My_Script{"test",123}),titlepage]
@@ -652,8 +648,7 @@
%D
%D \showsetup{definereference}
%D
-%D We can trace references by setting the next switch to
-%D true.
+%D We can trace references by setting the next switch to true.
\unexpanded\def\definereference
{\dodoubleempty\strc_references_define_reference}
@@ -673,23 +668,22 @@
%D \goto{somewhere}[JS(somescript),nextpage,JS(anotherscript)]
%D \stoptyping
%D
-%D Actually supporting chains is up to the special driver. Here
-%D we only provide the hooks.
+%D Actually supporting chains is up to the special driver. Here we only provide the
+%D hooks.
%D \macros
%D {highlighthyperlinks}
%D
-%D The next switch can be used to make user hyperlinks are
-%D not highlighted when clicked on.
+%D The next switch can be used to make user hyperlinks are not highlighted when
+%D clicked on.
\newconditional\highlighthyperlinks \settrue\highlighthyperlinks
%D \macros
%D {gotonewwindow}
%D
-%D To make the {\em goto previous jump} feature more
-%D convenient when using more than one file, it makes sense
-%D to force the viewer to open a new window for each file
+%D To make the {\em goto previous jump} feature more convenient when using more than
+%D one file, it makes sense to force the viewer to open a new window for each file
%D opened.
\newconditional\gotonewwindow \setfalse\gotonewwindow
@@ -708,13 +702,11 @@
\let\doifreferencefoundelse \doifelsereferencefound
-%D The tester only splits the reference in components but does
-%D not look into them. The following macro does a preroll and
-%D determines for instance the current real reference pagenumber.
-%D The \type {\currentrealreference} macro does the same so unless
-%D one wants to use the pagestate the next macro seldom needs to
-%D be called.
-
+%D The tester only splits the reference in components but does not look into them.
+%D The following macro does a preroll and determines for instance the current real
+%D reference pagenumber. The \type {\currentrealreference} macro does the same so
+%D unless one wants to use the pagestate the next macro seldom needs to be called.
+%D
%D The inner case is simple. Only two cases have to be taken
%D care of:
%D
@@ -723,8 +715,8 @@
%D \goto{some text}[prefix:reference]
%D \stoptyping
%D
-%D References to other files however are treated strict or
-%D tolerant, depending on their loading and availability:
+%D References to other files however are treated strict or tolerant, depending on
+%D their loading and availability:
%D
%D \starttyping
%D \useexternaldocument[somefile][filename][a nice description]
@@ -734,72 +726,61 @@
%D \goto{unchecked reference}[anotherfile::reference]
%D \stoptyping
%D
-%D An unknown reference is reported on the screen, in the log
-%D file and, when enabled, in the left margin of the text.
+%D An unknown reference is reported on the screen, in the log file and, when
+%D enabled, in the left margin of the text.
\let\unknownreference\gobbleoneargument
-%D When a reference is not found, we typeset a placeholder
-%D (two glyphs are often enough to represent the reference
-%D text).
+%D When a reference is not found, we typeset a placeholder (two glyphs are often
+%D enough to represent the reference text).
\def\dummyreference{{\tttf ??}}
\def\emptyreference{{\tttf !!}}
-%D To prevent repetitive messages concerning a reference
-%D being defined, we set such an unknown reference to an empty
-%D one after the first encounter.
-
-%D Apart from cross references supplied by the user, \CONTEXT\
-%D generates cross references itself. Most of them are not
-%D saved as a reference, but stored with their source, for
-%D instance a list or an index entry. Such automatically
-%D generated, for the user invisible, references are called
-%D {\em internal references}. The user supplied ones are
-%D labeled as {\em external references}.
-%D
-%D A second important characteristic is that when we want to
-%D support different backends (viewers), we need to support
-%D named destinations as well as page numbers. I invite readers
-%D to take a glance at the special driver modules to understand
-%D the fine points of this. As a result we will deal with {\em
-%D locations} as well as {\em real page numbers}. We explictly
-%D call this pagenumber a real one, because it is independant
-%D of the page numbering scheme used in the document.
-%D
-%D One of the reasons for \CONTEXT\ being the first \TEX\ base
-%D macropackage to support sophisticated interactive \PDF\
-%D files, lays in the mere fact that real page numbers are
-%D available in most two pass data, like references, list data
-%D and index entries.
-%D
-%D We will speak of \type{thisis...} when we are marking a
-%D location, and \type{goto...} when we point to such a
-%D location. The latter one can be seen as a hyperlink to the
-%D former one. In the next macros one we use constructs like:
+%D To prevent repetitive messages concerning a reference being defined, we set such
+%D an unknown reference to an empty one after the first encounter.
+%D
+%D Apart from cross references supplied by the user, \CONTEXT\ generates cross
+%D references itself. Most of them are not saved as a reference, but stored with
+%D their source, for instance a list or an index entry. Such automatically
+%D generated, for the user invisible, references are called {\em internal
+%D references}. The user supplied ones are labeled as {\em external references}.
+%D
+%D A second important characteristic is that when we want to support different
+%D backends (viewers), we need to support named destinations as well as page
+%D numbers. I invite readers to take a glance at the special driver modules to
+%D understand the fine points of this. As a result we will deal with {\em locations}
+%D as well as {\em real page numbers}. We explictly call this pagenumber a real one,
+%D because it is independant of the page numbering scheme used in the document.
+%D
+%D One of the reasons for \CONTEXT\ being the first \TEX\ base macropackage to
+%D support sophisticated interactive \PDF\ files, lays in the mere fact that real
+%D page numbers are available in most two pass data, like references, list data and
+%D index entries.
+%D
+%D We will speak of \type {thisis...} when we are marking a location, and
+%D \type {goto...} when we point to such a location. The latter one can be seen as a
+%D hyperlink to the former one. In the next macros one we use constructs like:
%D
%D \starttyping
%D \dostart...
%D \dostop...
%D \stoptyping
%D
-%D Such macros are used to invoke the relevant specials from
-%D the special driver modules (see \type{spec-ini}). The flag
-%D \type{\iflocation} signals if we're in interactive mode.
+%D The flag \type {\iflocation} signals if we're in interactive mode.
\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
-%D completely up to the macros that call them.
+%D Internal references can best be set using the next few macros. Setting such
+%D references to unique values is completely up to the macros that call them.
%D
%D \starttyping
%D \thisissomeinternal{tag}{identifier}
%D \gotosomeinternal {tag}{identifier}{pagenumber}{text}
%D \stoptyping
-
-%D We could do this in lua ...
+%D
+%D We could do this in \LUA\ \unknown
\newif \iflocation
\newcount\locationcount
@@ -823,7 +804,7 @@
\clf_setinternalreference
reference {#kind:#name}% no view
\relax
- \hbox attr \destinationattribute\lastdestinationattribute{}%
+ \hpack attr \destinationattribute\lastdestinationattribute{}%
\endgroup}
\installcorenamespace{savedinternalreference}
@@ -845,12 +826,10 @@
\def\gotonextinternal#text#target%
{\directgoto{#text}[internal(#target)]}
-%D In this module we define three system references: one for
-%D handling navigational, viewer specific, commands, another
-%D for jumping to special pages, like the first or last one,
-%D and a third reference for linking tree like lists, like
-%D tables of contents. The latter two adapt themselves to the
-%D current state.
+%D In this module we define three system references: one for handling navigational,
+%D viewer specific, commands, another for jumping to special pages, like the first
+%D or last one, and a third reference for linking tree like lists, like tables of
+%D contents. The latter two adapt themselves to the current state.
%D
%D An example of an action is:
%D
@@ -863,11 +842,10 @@
%D \starttyping
%D \goto{some text}[\v!action(PreviousJump]
%D \stoptyping
-
-%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
-%D reset. Other values become the prefix.
+%D
+%D One can also activate an automatic prefix mechanism. By setting the
+%D \type {\prefix} variable to \type {+}, the prefix is incremented, when set to
+%D \type {-} or empty, the prefix is reset. Other values become the prefix.
\newcount\prefixcounter
@@ -892,13 +870,6 @@
\unexpanded\def\setupglobalreferenceprefix[#prefix]%
{\xdef\referenceprefix{#prefix}}
-% \unexpanded\def\pushreferenceprefix#prefix%
-% {\pushmacro\referenceprefix
-% \xdef\referenceprefix{#prefix}} % global
-
-% \unexpanded\def\popreferenceprefix
-% {\popmacro\referenceprefix}
-
\unexpanded\def\globalpushreferenceprefix#prefix%
{\xdef\referenceprefix{\clf_pushreferenceprefix{#prefix}}}
@@ -935,16 +906,14 @@
\setupreferenceprefix[\referencingparameter\c!prefix]
\to \everysetupreferencing
-%D We can typeset a reference using \type{\in}, \type{\at} and
-%D \type{\about} and goto specific locations using
-%D \type{\goto}. The last one does not make that much sense in
-%D a paper document. To complicate things, \PLAIN\ \TEX\ also
-%D implements an \type {\in} but fortunately that one only
-%D makes sense in math mode.
+%D We can typeset a reference using \type {\in}, \type {\at} and \type {\about} and
+%D goto specific locations using \type {\goto}. The last one does not make that much
+%D sense in a paper document. To complicate things, \PLAIN\ \TEX\ also implements an
+%D \type {\in} but fortunately that one only makes sense in math mode.
%D
-%D Typesetting the reference is a bit more complicated than one
-%D would at first sight expect. This is due to the fact that we
-%D distinguish three (five) alternative calls:
+%D Typesetting the reference is a bit more complicated than one would at first sight
+%D expect. This is due to the fact that we distinguish three (five) alternative
+%D calls:
%D
%D \placefigure
%D [here][three calls]
@@ -971,25 +940,11 @@
%D \getbuffer
%D \stoplines
%D
-%D The dual \type{{}} results in a split reference. In a
-%D document meant for paper, one is tempted to use the last
-%D (most straightforward) alternative. When a document is also
-%D meant voor electronic distribution, the former alternatives
-%D have preference, because everything between the \type{\in}
-%D and~\type{[} becomes active (and when asked for, typeset
-%D in a different color and typeface).
-
-% \unexpanded\def\in {\mathortext\donormalmathin \strc_references_in}
-% \unexpanded\def\at {\mathortext\donormalmathat \strc_references_at}
-% \unexpanded\def\about{\mathortext\donormalmathabout\strc_references_about}
-% \unexpanded\def\from {\mathortext\donormalmathfrom \strc_references_from}
-% \unexpanded\def\over {\mathortext\donormalmathover \strc_references_about}
-
-% \definecommand in {\strc_references_in}
-% \definecommand at {\strc_references_at}
-% \definecommand about {\strc_references_about}
-% \definecommand from {\strc_references_from}
-% \definecommand over {\strc_references_about} % needed here, else math problems
+%D The dual \type {{}} results in a split reference. In a document meant for paper,
+%D one is tempted to use the last (most straightforward) alternative. When a
+%D document is also meant voor electronic distribution, the former alternatives have
+%D preference, because everything between the \type {\in} and~\type {[} becomes
+%D active (and when asked for, typeset in a different color and typeface).
\appendtoks
\ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \strc_references_in } \else \let\in \strc_references_in \fi
@@ -1009,8 +964,7 @@
\def\currentreferencedefault {\clf_filterreference{default}}
\def\currentreferencerealpage{\clf_filterreference{realpage}}
-%D The most straightforward way of retrieving references is
-%D using \type{\ref}.
+%D The most straightforward way of retrieving references is using \type {\ref}.
\unexpanded\def\getreference % checking, unexpanded
{\dodoubleargument\strc_references_get_reference}
@@ -1040,12 +994,11 @@
\referencingparameter\c!right
\endgroup}
-%D The previously discussed setup macro lets us specify the
-%D representation of references. A symbol reference does not
-%D show the specific data, like the number of a figure, but
-%D shows one of: \hbox {$^\goforwardcharacter$
-%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending
-%D on the direction to go.
+%D The previously discussed setup macro lets us specify the representation of
+%D references. A symbol reference does not show the specific data, like the number
+%D of a figure, but shows one of: \hbox {$^\goforwardcharacter$
+%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending on the direction to
+%D go.
%D
%D \starttyping
%D ... \somewhere{backward text}{forward text}[someref] ...
@@ -1141,7 +1094,7 @@
\expandafter\sixthofsixarguments \fi}
\unexpanded\def\referencesymbol
- {\hbox\bgroup
+ {\hpack\bgroup
\strut
\markreferencepage
\high
@@ -1210,17 +1163,23 @@
\newtoks\defaultleftreferencetoks
\newtoks\defaultrightreferencetoks
-\def\leftofreferencecontent {\nobreakspace} % we cannot do \definereferenceformat[at] .. so we need this
+%def\leftofreferencecontent {\nobreakspace} % we cannot do \definereferenceformat[at] .. so we need this
\let\rightofreferencecontent \empty
\let\leftofreference \empty
\let\rightofreference \empty
+\unexpanded\def\leftofreferencecontent
+ {\removeunwantedspaces
+ \nonbreakablespace
+ \ignorespaces}
+
\installcorenamespace{referencinginteraction}
\def\strc_references_interaction_all
{\the\leftreferencetoks
\doifelsesometoks\leftreferencetoks \leftofreferencecontent \donothing
\leftofreference
+ \doifelsesometoks\leftreferencetoks\onlynonbreakablespace\relax % new, replace space by nonbreakable if present
\currentreferencecontent
\rightofreference
\doifelsesometoks\rightreferencetoks\rightofreferencecontent\donothing
@@ -1242,15 +1201,6 @@
\setvalue{\??referencinginteraction\v!symbol}%
{\referencesymbol}
-% \def\referencesequence
-% {\csname\??referencinginteraction
-% \ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname
-% \referencingparameter\c!interaction
-% \else
-% \v!all
-% \fi
-% \endcsname}
-
\def\referencesequence
{\ifcsname\??referencinginteraction\referencingparameter\c!interaction\endcsname
\expandafter\lastnamedcs
@@ -1311,9 +1261,8 @@
%D \macros
%D {definereferenceformat}
%D
-%D The next few macros were made for for David Arnold and Taco
-%D Hoekwater. They can be used for predefining reference
-%D texts, and thereby stimulate efficiency.
+%D The next few macros were made for for David Arnold and Taco Hoekwater. They can
+%D be used for predefining reference texts, and thereby stimulate efficiency.
%D
%D \starttyping
%D \definereferenceformat[informula] [left=(,right=),text=formula]
@@ -1328,11 +1277,11 @@
%D the \informulas [b] \andformula [for:c]
%D \stoptyping
%D
-%D Instead of a text, one can specify a label, which should
-%D be defined with \type {\setuplabeltext}.
+%D Instead of a text, one can specify a label, which should be defined with \type
+%D {\setuplabeltext}.
%D
-%D Watch out: the second argument is somewhat special and mostly
-%D meant for a suffix to a number:
+%D Watch out: the second argument is somewhat special and mostly meant for a suffix
+%D to a number:
%D
%D \startbuffer
%D \definereferenceformat [intesta] [left=(,right=),text=Whatever~]
@@ -1437,21 +1386,18 @@
%
% \definereferenceformat[hellup][text=Hellup ,setups=referenceformat:numberplustext]
-%D In interactive documents going to a specific location is not
-%D bound to cross references. The \type{\goto} commands can be
-%D used to let users access another part of the document. In
-%D this respect, interactive tables of contents and registers
-%D can be considered goto's. Because in fact a \type{\goto} is
-%D just a reference without reference specific data, the
-%D previous macros are implemented using the goto
-%D functionality.
+%D In interactive documents going to a specific location is not bound to cross
+%D references. The \type {\goto} commands can be used to let users access another
+%D part of the document. In this respect, interactive tables of contents and
+%D registers can be considered goto's. Because in fact a \type {\goto} is just a
+%D reference without reference specific data, the previous macros are implemented
+%D using the goto functionality.
%D
%D \showsetup{goto}
%D
-%D One important characteristic is that the first argument of
-%D \type{\goto} (and therefore \type{\at} and \type{\in} is
-%D split at spaces. This means that, although hyphenation is
-%D prevented, long references can cross line endings.
+%D One important characteristic is that the first argument of \type {\goto} (and
+%D therefore \type {\at} and \type {\in} is split at spaces. This means that,
+%D although hyphenation is prevented, long references can cross line endings.
% \starttext
% \setupinteraction[state=start]
@@ -1740,21 +1686,19 @@
\clf_doifelsereference{\referenceprefix}{#label}{\extrareferencearguments}%
{\clf_injectcurrentreference
\global\lastsavedreferenceattribute\lastreferenceattribute
- \hbox attr \referenceattribute \lastreferenceattribute {\box\scratchbox}}
+ \hpack attr \referenceattribute \lastreferenceattribute {\box\scratchbox}}
{\box\scratchbox}%
\endgroup}
-%D An reference to another document can be specified as a file
-%D or as an \URL. Both are handled by the same mechanism and
-%D can be issued by saying something like:
+%D An reference to another document can be specified as a file or as an \URL. Both
+%D are handled by the same mechanism and can be issued by saying something like:
%D
%D \starttyping
%D \goto[dictionary::the letter a]
%D \stoptyping
%D
-%D One can imagine that many references to such a dictionary
-%D are made, so in most cases such a document reference in an
-%D indirect one.
+%D One can imagine that many references to such a dictionary are made, so in most
+%D cases such a document reference in an indirect one.
%D
%D \showsetup{useexternaldocument}
%D
@@ -1766,8 +1710,8 @@
%D [The Famous English Dictionary]
%D \stoptyping
%D
-%D The next macro implements these relations, and also take
-%D care of loading the document specific references.
+%D The next macro implements these relations, and also take care of loading the
+%D document specific references.
%D
%D The \URL\ alternative takes four arguments:
%D
@@ -1789,9 +1733,8 @@
%D \useURL [id] [url]
%D \stoptyping
%D
-%D This time we don't load the references when no file is
-%D specified. This is logical when one keeps in mind that a
-%D valid \URL\ can also be a mail address.
+%D This time we don't load the references when no file is specified. This is logical
+%D when one keeps in mind that a valid \URL\ can also be a mail address.
\unexpanded\def\useurl {\doquadrupleempty\strc_references_use_url } % so that they can be used in expanded arguments
\unexpanded\def\usefile{\dotripleargument\strc_references_use_file} % so that they can be used in expanded arguments
@@ -1814,8 +1757,7 @@
%D \macros
%D {url,setupurl}
%D
-%D We also have: \type{\url} for directly calling the
-%D description. So we can say:
+%D We also have: \type {\url} for directly calling the description. So we can say:
%D
%D \starttyping
%D \useURL [one] [http://www.test.nl]
@@ -1843,8 +1785,8 @@
\hyphenatedurl{\clf_geturl{#label}}%
\endgroup}
-%D This macro is hooked into a support macro, and thereby
-%D \URL's break ok, according to the setting of a switch,
+%D This macro is hooked into a support macro, and thereby \URL's break ok, according
+%D to the setting of a switch,
%D
%D \startbuffer
%D \useURL
@@ -1858,9 +1800,8 @@
%D
%D \getbuffer
-%D When defining the external source of information, one can
-%D also specify a suitable name (the last argument). This name
-%D can be called upon with:
+%D When defining the external source of information, one can also specify a suitable
+%D name (the last argument). This name can be called upon with:
%D
%D \showsetup{from}
%D
@@ -1895,9 +1836,8 @@
%D \goto{some text}[identifier::location]
%D \stoptyping
-%D A special case of references are those to programs. These,
-%D very system dependant references are implemented by abusing
-%D some of the previous macros.
+%D A special case of references are those to programs. These, very system dependant
+%D references are implemented by abusing some of the previous macros.
%D
%D \showsetup{setupprograms}
%D \showsetup{defineprogram}
@@ -1918,15 +1858,14 @@
\def\strc_references_define_program[#name][#program][#description]%
{\clf_defineprogram{#name}{#program}{#description}}
-\def\program[#name]% incompatible, more consistent, hardy used anyway
+\unexpanded\def\program[#name]% incompatible, more consistent, hardy used anyway
{\dontleavehmode
\begingroup
\useprogramsstyleandcolor\c!style\c!color
\clf_getprogram{#name}%
\endgroup}
-%D As we can see, we directly use the special reference
-%D mechanism, which means that
+%D As we can see, we directly use the special reference mechanism, which means that
%D
%D \starttyping
%D \goto{some text}[program(name{args})]
@@ -1934,11 +1873,10 @@
%D
%D is valid.
-%D The next macro provides access to the actual pagenumbers.
-%D When documenting and sanitizing the original reference
-%D macros, I decided to keep the present meaning as well as to
-%D make this meaning available as a special reference method.
-%D So now one can use:
+%D The next macro provides access to the actual pagenumbers. When documenting and
+%D sanitizing the original reference macros, I decided to keep the present meaning
+%D as well as to make this meaning available as a special reference method. So now
+%D one can use:
%D
%D \starttyping
%D \gotopage{some text}[location]
@@ -1967,8 +1905,7 @@
\def\gotopage#text[#target]%
{\goto{#text}[\v!page(#target)]}
-%D The previous definitions are somewhat obsolete so we don't
-%D use it here.
+%D The previous definitions are somewhat obsolete so we don't use it here.
%D We can cross link documents by using:
%D
@@ -1980,16 +1917,14 @@
%D \coupledocument[print][somefile][chapter,section]
%D \stoptyping
%D
-%D After which when applicable, we have available the
-%D references:
+%D After which when applicable, we have available the references:
%D
%D \starttyping
%D \goto{print version}[print::chapter]
%D \stoptyping
%D
-%D and alike. The title placement definition macros have a
-%D key \type{file}, which is interpreted as the file to jump
-%D to, that is, when one clicks on the title.
+%D and alike. The title placement definition macros have a key \type {file}, which
+%D is interpreted as the file to jump to, that is, when one clicks on the title.
\def\coupledocument
{\doquadrupleempty\strc_references_couple_document}
@@ -2002,8 +1937,8 @@
%D \macros
%D {dotextprefix}
%D
-%D In previous macros we used \type {\dotextprefix} to
-%D generate a space between a label and a number.
+%D In previous macros we used \type {\dotextprefix} to generate a space between
+%D a label and a number.
%D
%D \starttyping
%D \dotextprefix{text}
@@ -2026,9 +1961,8 @@
\fi
\endgroup}
-%D In the next settings we see some variables that were not
-%D used here and that concern the way the pagenumbers refered
-%D to are typeset.
+%D In the next settings we see some variables that were not used here and that
+%D concern the way the pagenumbers refered to are typeset.
\setupreferencing
[\c!state=\v!start,
diff --git a/tex/context/base/mkiv/strc-reg.lua b/tex/context/base/mkiv/strc-reg.lua
index 2c667fba3..47ba1c533 100644
--- a/tex/context/base/mkiv/strc-reg.lua
+++ b/tex/context/base/mkiv/strc-reg.lua
@@ -7,7 +7,7 @@ if not modules then modules = { } end modules ['strc-reg'] = {
}
local next, type, tonumber = next, type, tonumber
-local format, gmatch = string.format, string.gmatch
+local char, format, gmatch = string.char, string.format, string.gmatch
local equal, concat, remove = table.are_equal, table.concat, table.remove
local lpegmatch, P, C, Ct = lpeg.match, lpeg.P, lpeg.C, lpeg.Ct
local allocate = utilities.storage.allocate
@@ -38,6 +38,7 @@ local texgetcount = tex.getcount
local variables = interfaces.variables
local v_forward = variables.forward
local v_all = variables.all
+local v_no = variables.no
local v_yes = variables.yes
local v_packed = variables.packed
local v_current = variables.current
@@ -47,7 +48,7 @@ local v_last = variables.last
local v_text = variables.text
local context = context
-local commands = commands
+local ctx_latelua = context.latelua
local implement = interfaces.implement
@@ -81,10 +82,12 @@ local ctx_startregisterpages = context.startregisterpages
local ctx_stopregisterpages = context.stopregisterpages
local ctx_startregisterseewords = context.startregisterseewords
local ctx_stopregisterseewords = context.stopregisterseewords
+
local ctx_registerentry = context.registerentry
local ctx_registerseeword = context.registerseeword
local ctx_registerpagerange = context.registerpagerange
local ctx_registeronepage = context.registeronepage
+
local ctx_registerpacked = context.registerpacked
-- possible export, but ugly code (overloads)
@@ -452,23 +455,6 @@ local tagged = { }
local function preprocessentries(rawdata)
local entries = rawdata.entries
if entries then
- --
- -- local e = entries[1] or ""
- -- local k = entries[2] or ""
- -- local et, kt, entryproc, pageproc
- -- if type(e) == "table" then
- -- et = e
- -- else
- -- entryproc, e = splitprocessor(e)
- -- et = lpegmatch(entrysplitter,e)
- -- end
- -- if type(k) == "table" then
- -- kt = k
- -- else
- -- pageproc, k = splitprocessor(k)
- -- kt = lpegmatch(entrysplitter,k)
- -- end
- --
local processors = rawdata.processors
local et = entries.entries
local kt = entries.keys
@@ -533,6 +519,7 @@ local function storeregister(rawdata) -- metadata, references, entries
metadata.kind = "entry"
end
--
+ --
if not metadata.catcodes then
metadata.catcodes = tex.catcodetable -- get
end
@@ -581,17 +568,20 @@ local function storeregister(rawdata) -- metadata, references, entries
return #entries
end
-registers.store = storeregister
-
-function registers.enhance(name,n)
- local data = tobesaved[name].metadata.notsaved and collected[name] or tobesaved[name]
+local function enhanceregister(specification)
+ local name = specification.name
+ local n = specification.n
+ local saved = tobesaved[name]
+ local data = saved.metadata.notsaved and collected[name] or saved
local entry = data.entries[n]
if entry then
entry.references.realpage = texgetcount("realpageno")
end
end
-function registers.extend(name,tag,rawdata) -- maybe do lastsection internally
+-- This can become extendregister(specification)!
+
+local function extendregister(name,tag,rawdata) -- maybe do lastsection internally
if type(tag) == "string" then
tag = tagged[tag]
end
@@ -635,6 +625,10 @@ function registers.extend(name,tag,rawdata) -- maybe do lastsection internally
end
end
+registers.store = storeregister
+registers.enhance = enhanceregister
+registers.extend = extendregister
+
function registers.get(tag,n)
local list = tobesaved[tag]
return list and list.entries[n]
@@ -642,13 +636,24 @@ end
implement {
name = "enhanceregister",
- actions = registers.enhance,
arguments = { "string", "integer" },
+ actions = function(name,n)
+ enhanceregister { name = name, n = n } -- todo: move to scanner
+ end,
+}
+
+implement {
+ name = "deferredenhanceregister",
+ arguments = { "string", "integer" },
+ protected = true,
+ actions = function(name,n)
+ ctx_latelua { action = enhanceregister, name = name, n = n }
+ end,
}
implement {
name = "extendregister",
- actions = registers.extend,
+ actions = extendregister,
arguments = "2 strings",
}
@@ -714,7 +719,8 @@ function registers.compare(a,b)
local ka = a.metadata.kind
local kb = b.metadata.kind
if ka == kb then
- local page_a, page_b = a.references.realpage, b.references.realpage
+ local page_a = a.references.realpage
+ local page_b = b.references.realpage
if not page_a or not page_b then
return 0
elseif page_a < page_b then
@@ -739,7 +745,7 @@ local seeindex = 0
-- meerdere loops, seewords, dan words, anders seewords
-local function crosslinkseewords(result) -- all words
+local function crosslinkseewords(result,check) -- all words
-- collect all seewords
local seewords = { }
for i=1,#result do
@@ -783,24 +789,17 @@ local function crosslinkseewords(result) -- all words
local seeparent = seeparents[text]
if seeparent then
local seeindex = seewords[text]
- local s, ns, d, w, l = { }, 0, data.split, seeparent.split, data.list
- -- trick: we influence sorting by adding fake subentries
- for i=1,#d do
- ns = ns + 1
- s[ns] = d[i] -- parent
- end
- for i=1,#w do
- ns = ns + 1
- s[ns] = w[i] -- see
- end
- data.split = s
- -- we also register a fake extra list entry so that the
- -- collapser works okay
- l[#l+1] = { text, "" }
data.references.seeindex = seeindex
if trace_registers then
report_registers("see crosslink %03i: %s",seeindex,text)
end
+ seeword.valid = true
+ elseif check then
+ report_registers("invalid crosslink : %s, %s",text,"ignored")
+ seeword.valid = false
+ else
+ report_registers("invalid crosslink : %s, %s",text,"passed")
+ seeword.valid = true
end
end
end
@@ -824,17 +823,22 @@ local function removeemptyentries(result)
end
end
-function registers.prepare(data)
+function registers.prepare(data,options)
-- data has 'list' table
local strip = sorters.strip
local splitter = sorters.splitters.utf
local result = data.result
if result then
+ local seeprefix = char(0)
for i=1, #result do
local entry = result[i]
local split = { }
local list = entry.list
if list then
+ if entry.seeword then
+ -- we can have multiple seewords, only two levels supported
+ list[#list+1] = { seeprefix .. strip(entry.seeword.text) }
+ end
for l=1,#list do
local ll = list[l]
local word = ll[1]
@@ -848,7 +852,7 @@ function registers.prepare(data)
entry.split = split
end
removeemptyentries(result)
- crosslinkseewords(result)
+ crosslinkseewords(result,options.check ~= v_no)
end
end
@@ -861,7 +865,9 @@ function registers.sort(data,options)
end
function registers.unique(data,options)
- local result, nofresult, prev = { }, 0, nil
+ local result = { }
+ local nofresult = 0
+ local prev = nil
local dataresult = data.result
for k=1,#dataresult do
local v = dataresult[k]
@@ -873,7 +879,8 @@ function registers.unique(data,options)
elseif pr.realpage ~= vr.realpage then
-- ok
else
- local pl, vl = pr.lastrealpage, vr.lastrealpage
+ local pl = pr.lastrealpage
+ local vl = vr.lastrealpage
if pl or vl then
if not vl then
-- ok
@@ -901,7 +908,11 @@ end
function registers.finalize(data,options) -- maps character to index (order)
local result = data.result
data.metadata.nofsorted = #result
- local split, nofsplit, lasttag, done, nofdone = { }, 0, nil, nil, 0
+ local split = { }
+ local nofsplit = 0
+ local lasttag = nil
+ local done = nil
+ local nofdone = 0
local firstofsplit = sorters.firstofsplit
for k=1,#result do
local v = result[k]
@@ -922,8 +933,46 @@ function registers.finalize(data,options) -- maps character to index (order)
data.result = split
end
+-- local function analyzeregister(class,options)
+-- local data = collected[class]
+-- if data and data.entries then
+-- options = options or { }
+-- sorters.setlanguage(options.language,options.method,options.numberorder)
+-- registers.filter(data,options) -- filter entries into results (criteria)
+-- registers.prepare(data,options) -- adds split table parallel to list table
+-- registers.sort(data,options) -- sorts results
+-- registers.unique(data,options) -- get rid of duplicates
+-- registers.finalize(data,options) -- split result in ranges
+-- data.metadata.sorted = true
+-- return data.metadata.nofsorted or 0
+-- else
+-- return 0
+-- end
+-- end
+
local function analyzeregister(class,options)
- local data = collected[class]
+ local data = rawget(collected,class)
+ if not data then
+ local list = utilities.parsers.settings_to_array(class)
+ local entries = { }
+ local metadata = false
+ for i=1,#list do
+ local l = list[i]
+ local d = collected[l]
+ local e = d.entries
+ for i=1,#e do
+ entries[#entries+1] = e[i]
+ end
+ if not metadata then
+ metadata = d.metadata
+ end
+ end
+ data = {
+ metadata = metadata or { },
+ entries = entries,
+ }
+ collected[class] = data
+ end
if data and data.entries then
options = options or { }
sorters.setlanguage(options.language,options.method,options.numberorder)
@@ -973,8 +1022,10 @@ implement {
-- todo: ownnumber
local function pagerange(f_entry,t_entry,is_last,prefixspec,pagespec)
- local fer, ter = f_entry.references, t_entry.references
+ local fer = f_entry.references
+ local ter = t_entry.references
ctx_registerpagerange(
+ f_entry.metadata.name or "",
f_entry.processors and f_entry.processors[2] or "",
fer.internal or 0,
fer.realpage or 0,
@@ -996,6 +1047,7 @@ end
local function pagenumber(entry,prefixspec,pagespec)
local er = entry.references
ctx_registeronepage(
+ entry.metadata.name or "",
entry.processors and entry.processors[2] or "",
er.internal or 0,
er.realpage or 0,
@@ -1004,7 +1056,8 @@ local function pagenumber(entry,prefixspec,pagespec)
end
local function packed(f_entry,t_entry)
- local fer, ter = f_entry.references, t_entry.references
+ local fer = f_entry.references
+ local ter = t_entry.references
ctx_registerpacked(
fer.internal or 0,
ter.internal or 0
@@ -1013,8 +1066,12 @@ end
local function collapsedpage(pages)
for i=2,#pages do
- local first, second = pages[i-1], pages[i]
- local first_first, first_last, second_first, second_last = first[1], first[2], second[1], second[2]
+ local first = pages[i-1]
+ local second = pages[i]
+ local first_first = first[1]
+ local first_last = first[2]
+ local second_first = second[1]
+ local second_last = second[2]
local first_last_pn = first_last .references.realpage
local second_first_pn = second_first.references.realpage
local second_last_pn = second_last .references.realpage
@@ -1110,7 +1167,8 @@ function registers.flush(data,options,prefixspec,pagespec)
done[i] = false
end
local data = sublist.data
- local d, n = 0, 0
+ local d = 0
+ local n = 0
ctx_startregistersection(sublist.tag)
for d=1,#data do
local entry = data[d]
@@ -1126,6 +1184,7 @@ function registers.flush(data,options,prefixspec,pagespec)
end
-- ok, this is tricky: we use e[i] delayed so we need it to be local
-- but we don't want to allocate too many entries so there we go
+
while d < #data do
d = d + 1
local entry = data[d]
@@ -1164,8 +1223,8 @@ function registers.flush(data,options,prefixspec,pagespec)
started = false
end
if n == i then
--- ctx_stopregisterentries()
--- ctx_startregisterentries(n)
+ -- ctx_stopregisterentries()
+ -- ctx_startregisterentries(n)
else
while n > i do
n = n - 1
@@ -1186,127 +1245,131 @@ function registers.flush(data,options,prefixspec,pagespec)
ctx_startregisterentry(0) -- will become a counter
started = true
if metadata then
- ctx_registerentry(processor,internal,seeparent,function() h_title(e[i],metadata) end)
+ ctx_registerentry(metadata.name or "",processor,internal,seeparent,function() h_title(e[i],metadata) end)
else
-- can this happen?
- ctx_registerentry(processor,internal,seeindex,e[i])
+ ctx_registerentry("",processor,internal,seeindex,e[i])
end
end
end
- if kind == 'entry' then
- if show_page_number then
- ctx_startregisterpages()
- if collapse_singles or collapse_ranges then
- -- we collapse ranges and keep existing ranges as they are
- -- so we get prebuilt as well as built ranges
- local first, last, prev, pages, dd, nofpages = entry, nil, entry, { }, d, 0
- while dd < #data do
- dd = dd + 1
- local next = data[dd]
- if next and next.metadata.kind == "see" then
- dd = dd - 1
- break
- else
- local el, nl = entry.list, next.list
- if not equal(el,nl) then
- dd = dd - 1
- --~ first = nil
- break
- elseif next.references.lastrealpage then
- nofpages = nofpages + 1
- pages[nofpages] = first and { first, last or first } or { entry, entry }
- nofpages = nofpages + 1
- pages[nofpages] = { next, next }
- first, last, prev = nil, nil, nil
- elseif not first then
- first, prev = next, next
- elseif next.references.realpage - prev.references.realpage == 1 then -- 1 ?
- last, prev = next, next
- else
- nofpages = nofpages + 1
- pages[nofpages] = { first, last or first }
- first, last, prev = next, nil, next
- end
- end
- end
- if first then
+
+ local function case_1()
+ -- we collapse ranges and keep existing ranges as they are
+ -- so we get prebuilt as well as built ranges
+ local first, last, prev, pages, dd, nofpages = entry, nil, entry, { }, d, 0
+ while dd < #data do
+ dd = dd + 1
+ local next = data[dd]
+ if next and next.metadata.kind == "see" then
+ dd = dd - 1
+ break
+ else
+ local el, nl = entry.list, next.list
+ if not equal(el,nl) then
+ dd = dd - 1
+ --~ first = nil
+ break
+ elseif next.references.lastrealpage then
+ nofpages = nofpages + 1
+ pages[nofpages] = first and { first, last or first } or { entry, entry }
+ nofpages = nofpages + 1
+ pages[nofpages] = { next, next }
+ first, last, prev = nil, nil, nil
+ elseif not first then
+ first, prev = next, next
+ elseif next.references.realpage - prev.references.realpage == 1 then -- 1 ?
+ last, prev = next, next
+ else
nofpages = nofpages + 1
pages[nofpages] = { first, last or first }
+ first, last, prev = next, nil, next
end
- if collapse_ranges and nofpages > 1 then
- nofpages = collapsepages(pages)
- end
- if nofpages > 0 then -- or 0
- d = dd
- for p=1,nofpages do
- local first, last = pages[p][1], pages[p][2]
- if first == last then
- if first.references.lastrealpage then
- pagerange(first,first,true,prefixspec,pagespec)
- else
- pagenumber(first,prefixspec,pagespec)
- end
- elseif last.references.lastrealpage then
- pagerange(first,last,true,prefixspec,pagespec)
- else
- pagerange(first,last,false,prefixspec,pagespec)
- end
+ end
+ end
+ if first then
+ nofpages = nofpages + 1
+ pages[nofpages] = { first, last or first }
+ end
+ if collapse_ranges and nofpages > 1 then
+ nofpages = collapsepages(pages)
+ end
+ if nofpages > 0 then -- or 0
+ d = dd
+ for p=1,nofpages do
+ local first, last = pages[p][1], pages[p][2]
+ if first == last then
+ if first.references.lastrealpage then
+ pagerange(first,first,true,prefixspec,pagespec)
+ else
+ pagenumber(first,prefixspec,pagespec)
end
- elseif entry.references.lastrealpage then
- pagerange(entry,entry,true,prefixspec,pagespec)
+ elseif last.references.lastrealpage then
+ pagerange(first,last,true,prefixspec,pagespec)
else
- pagenumber(entry,prefixspec,pagespec)
+ pagerange(first,last,false,prefixspec,pagespec)
end
- elseif collapse_packed then
- local first = nil
- local last = nil
- while true do
- if not first then
- first = entry
- end
- last = entry
- if d == #data then
- break
- else
- d = d + 1
- local next = data[d]
- if next.metadata.kind == "see" or not equal(entry.list,next.list) then
- d = d - 1
- break
- else
- entry = next
- end
- end
+ end
+ elseif entry.references.lastrealpage then
+ pagerange(entry,entry,true,prefixspec,pagespec)
+ else
+ pagenumber(entry,prefixspec,pagespec)
+ end
+ end
+
+ local function case_2()
+ local first = nil
+ local last = nil
+ while true do
+ if not first then
+ first = entry
+ end
+ last = entry
+ if d == #data then
+ break
+ else
+ d = d + 1
+ local next = data[d]
+ if next.metadata.kind == "see" or not equal(entry.list,next.list) then
+ d = d - 1
+ break
+ else
+ entry = next
end
- packed(first,last) -- returns internals
+ end
+ end
+ packed(first,last) -- returns internals
+ end
+
+ local function case_3()
+ while true do
+ if entry.references.lastrealpage then
+ pagerange(entry,entry,true,prefixspec,pagespec)
else
- while true do
- if entry.references.lastrealpage then
- pagerange(entry,entry,true,prefixspec,pagespec)
- else
- pagenumber(entry,prefixspec,pagespec)
- end
- if d == #data then
- break
- else
- d = d + 1
- local next = data[d]
- if next.metadata.kind == "see" or not equal(entry.list,next.list) then
- d = d - 1
- break
- else
- entry = next
- end
- end
+ pagenumber(entry,prefixspec,pagespec)
+ end
+ if d == #data then
+ break
+ else
+ d = d + 1
+ local next = data[d]
+ if next.metadata.kind == "see" or not equal(entry.list,next.list) then
+ d = d - 1
+ break
+ else
+ entry = next
end
end
- ctx_stopregisterpages()
end
- elseif kind == 'see' then
- local t, nt = { }, 0
+ end
+
+ local function case_4()
+ local t = { }
+ local nt = 0
while true do
- nt = nt + 1
- t[nt] = entry
+ if entry.seeword and entry.seeword.valid then
+ nt = nt + 1
+ t[nt] = entry
+ end
if d == #data then
break
else
@@ -1320,19 +1383,36 @@ function registers.flush(data,options,prefixspec,pagespec)
end
end
end
- ctx_startregisterseewords()
for i=1,nt do
- local entry = t[i]
+ local entry = t[i]
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 ""
- -- ctx_registerseeword(i,nt,processor,0,seeindex,seetext)
- ctx_registerseeword(i,nt,processor,0,seeindex,function() h_title(seetext,metadata) end)
+ ctx_registerseeword(metadata.name or "",i,nt,processor,0,seeindex,function() h_title(seetext,metadata) end)
end
+ end
+
+ if kind == "entry" then
+ if show_page_number then
+ ctx_startregisterpages()
+ if collapse_singles or collapse_ranges then
+ case_1()
+ elseif collapse_packed then
+ case_2()
+ else
+ case_3()
+ end
+ ctx_stopregisterpages()
+ end
+ elseif kind == "see" then
+ ctx_startregisterseewords()
+ case_4()
ctx_stopregisterseewords()
end
+
end
+
if started then
ctx_stopregisterentry()
started = false
@@ -1373,6 +1453,7 @@ implement {
{ "numberorder" },
{ "compress" },
{ "criterium" },
+ { "check" },
{ "pagenumber", "boolean" },
},
{
diff --git a/tex/context/base/mkiv/strc-reg.mkiv b/tex/context/base/mkiv/strc-reg.mkiv
index 04fdef9ad..559e1bd42 100644
--- a/tex/context/base/mkiv/strc-reg.mkiv
+++ b/tex/context/base/mkiv/strc-reg.mkiv
@@ -83,6 +83,7 @@
\c!pagestyle=\v!slanted,
\c!indicator=\v!yes,
\c!criterium=\v!all,
+ \c!check=\v!yes, % check for weird see usage
%\c!command=,
\c!referencing=\v!on,
\c!location=\v!middle,
@@ -159,8 +160,8 @@
%D Registering:
-\global\let\currentregistername \empty
-\global\let\currentregisternumber\!!zerocount
+\glet\currentregistername \empty
+\glet\currentregisternumber\!!zerocount
\def\strc_registers_register_page_entry
{\iftrialtypesetting
@@ -175,33 +176,33 @@
\xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}%
\xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}%
\xmlstopraw
- \globallet\currentregistercoding\s!xml}
+ \glet\currentregistercoding\s!xml}
\def\strc_registers_register_page_expand_yes_entries
{\xdef\currentregisterentriesa{\registerparameter{\c!entries:1}}%
\xdef\currentregisterentriesb{\registerparameter{\c!entries:2}}%
\xdef\currentregisterentriesc{\registerparameter{\c!entries:3}}%
- \globallet\currentregistercoding\s!tex}
+ \glet\currentregistercoding\s!tex}
\def\strc_registers_register_page_expand_nop_entries
{\xdef\currentregisterentriesa{\detokenizedregisterparameter{\c!entries:1}}%
\xdef\currentregisterentriesb{\detokenizedregisterparameter{\c!entries:2}}%
\xdef\currentregisterentriesc{\detokenizedregisterparameter{\c!entries:3}}%
- \globallet\currentregistercoding\s!tex}
+ \glet\currentregistercoding\s!tex}
\def\strc_registers_register_page_expand_xml
{\xmlstartraw
\xdef\currentregisterentries{\registerparameter\c!entries}%
\xmlstopraw
- \globallet\currentregistercoding\s!xml}
+ \glet\currentregistercoding\s!xml}
\def\strc_registers_register_page_expand_yes
{\xdef\currentregisterentries{\registerparameter\c!entries}%
- \globallet\currentregistercoding\s!tex}
+ \glet\currentregistercoding\s!tex}
\def\strc_registers_register_page_expand_nop
{\xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}%
- \globallet\currentregistercoding\s!tex}
+ \glet\currentregistercoding\s!tex}
\def\strc_registers_register_page_expand_xml_keys
{\xmlstartraw
@@ -304,7 +305,7 @@
\ifx\currentregisterownnumber\v!yes
\glet\currentregistersynchronize\relax
\else
- \xdef\currentregistersynchronize{\ctxlatecommand{enhanceregister("\currentregister",\currentregisternumber)}}%
+ \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}%
\fi
\currentregistersynchronize % here?
% needs thinking ... bla\index{bla}. will break before the . but adding a
@@ -340,7 +341,7 @@
% internal \locationcount
% view {\interactionparameter\c!focus}%
\relax % this will change
- \xdef\currentregistersynchronize{\ctxlatecommand{enhanceregister("\currentregister",\currentregisternumber)}}%
+ \xdef\currentregistersynchronize{\clf_deferredenhanceregister{\currentregister}\number\currentregisternumber}%
\currentregistersynchronize % here?
\dostarttagged\t!registerlocation\currentregister
\attribute\destinationattribute\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup
@@ -352,16 +353,46 @@
\unexpanded\def\strc_registers_insert_entry[#1][#2]%
{\def\currentregister{#1}%
- \doifelse{\registerparameter\c!ownnumber}\v!yes
- \strc_registers_insert_entry_yes
- \strc_registers_insert_entry_nop
- {#2}}
+ \edef\p_ownnumber{\registerparameter\c!ownnumber}%
+ \ifx\p_ownnumber\v!yes
+ \expandafter\strc_registers_insert_entry_yes
+ \else
+ \expandafter\strc_registers_insert_entry_nop
+ \fi{#2}}
+
+% \def\strc_registers_insert_entry_nop#1#2%
+% {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}}
+%
+% \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}}{}}}
+%
+% less tokens passed (nicer for tracing) .. could become installable
+
+\def\strc_registers_insert_entry_nop
+ {\ifvmode
+ \expandafter\strc_registers_insert_entry_nop_par
+ \else
+ \expandafter\strc_registers_insert_entry_nop_txt
+ \fi}
+
+\def\strc_registers_insert_entry_yes
+ {\ifvmode
+ \expandafter\strc_registers_insert_entry_yes_par
+ \else
+ \expandafter\strc_registers_insert_entry_yes_txt
+ \fi}
+
+\def\strc_registers_insert_entry_nop_par#1#2%
+ {\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}}
-\def\strc_registers_insert_entry_nop#1#2%
- {\doflushatpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}}
+\def\strc_registers_insert_entry_yes_par#1#2#3%
+ {\flushatnextpar{\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}}
-\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}}{}}}
+\def\strc_registers_insert_entry_nop_txt#1#2%
+ {\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!entries={#2}}{}}
+
+\def\strc_registers_insert_entry_yes_txt#1#2#3%
+ {\strc_registers_register_page_entry\currentregister{\c!keys={#1},\c!alternative=#2,\c!entries={#3}}{}}
\unexpanded\def\startregister{\doquadrupleempty\strc_registers_start_entry}
\unexpanded\def\stopregister {\dodoubleargument\strc_registers_stop_entry}
@@ -403,14 +434,14 @@
\xmlstartraw
\xdef\currentregisterentries{\registerparameter\c!entries}%
\xmlstopraw
- \globallet\currentregistercoding\s!xml
+ \glet\currentregistercoding\s!xml
\else
\ifx\currentregisterexpansion\v!yes
\xdef\currentregisterentries{\registerparameter\c!entries}%
\else
\xdef\currentregisterentries{\detokenizedregisterparameter\c!entries}%
\fi
- \globallet\currentregistercoding\s!tex
+ \glet\currentregistercoding\s!tex
\fi
% I hate this kind of mess ... but it's a user request.
\ifx\currentregisterentries\empty
@@ -493,7 +524,7 @@
\xdef\currentregisterentries{\detokenize{#3}}% not ok yet
\xdef\currentregisterseeword{\detokenize{#4}}% not ok yet
\xmlstopraw
- \globallet\currentregistercoding\s!xml
+ \glet\currentregistercoding\s!xml
\else
\ifx\currentregisterexpansion\v!yes
\xdef\currentregisterentries{#3}% not ok yet
@@ -502,7 +533,7 @@
\xdef\currentregisterentries{\detokenize{#3}}% not ok yet
\xdef\currentregisterseeword{\detokenize{#4}}% not ok yet
\fi
- \globallet\currentregistercoding\s!tex
+ \glet\currentregistercoding\s!tex
\fi
\setnextinternalreference
% we could consider storing register entries in list
@@ -544,8 +575,8 @@
\def\strc_registers_determine_characteristics[#1][#2]%
{\begingroup
- \edef\currentregister{#1}%
- \setupregister[\currentregister][#2]%
+ \setupregister[#1][#2]%
+ \edef\currentregister{\firstinset{#1}}%
\normalexpanded{\endgroup\noexpand\xdef\noexpand\utilityregisterlength{\clf_analyzeregister
{\currentregister}%
{%
@@ -569,6 +600,8 @@
\dontcomplain
\to \everyplaceregister
+\newconditional\c_strc_registers_text_interaction
+
\unexpanded\def\placeregister
{\dodoubleempty\strc_registers_place}
@@ -576,30 +609,29 @@
{\iffirstargument
\begingroup
%\forgetall
- \edef\currentregister{#1}%
- \setupregister[\currentregister][#2]%
+ \setupregister[#1][#2]% can be a list
+ \edef\currentregister{\firstinset{#1}}%
\the\everyplaceregister
\ifnum\namedmixedcolumnsparameter\currentregister\c!n>\plusone
\startmixedcolumns[\currentregister]
- \strc_registers_place_indeed
+ \strc_registers_place_indeed{#1}%
\stopmixedcolumns
\else
- \strc_registers_place_indeed
+ \strc_registers_place_indeed{#1}%
\fi
\endgroup
\fi}
-\newconditional\c_strc_registers_text_interaction
-
-\def\strc_registers_place_indeed
+\def\strc_registers_place_indeed#1%
{\doifelse{\registerparameter\c!interaction}\v!text
\settrue\setfalse\c_strc_registers_text_interaction
\clf_processregister
- {\currentregister}%
+ {#1}%
{%
language {\registerparameter\s!language}%
method {\registerparameter\c!method}%
numberorder {\registerparameter\c!numberorder}%
+ check {\registerparameter\c!check}%
compress {\registerparameter\c!compress}%
criterium {\registerparameter\c!criterium}%
pagenumber \ifx\registerpageseparatorsymbol\empty false\else true\fi
@@ -639,9 +671,9 @@
\def\strc_registers_complete[#1][#2]%
{\iffirstargument
\begingroup
- \edef\currentregister{#1}%
+ \edef\currentregister{\firstinset{#1}}%
\normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\currentregister}},reference=\currentregister]}%
- \placeregister[\currentregister][#2]%
+ \placeregister[#1][#2]%
\page[\v!yes]%
\stopnamedsection
\endgroup
@@ -835,15 +867,16 @@
\unexpanded\def\startregisterpages
{\begingroup
\dostarttagged\t!registerpages\empty
- \useregisterstyleandcolor\c!pagestyle\c!pagecolor}
+ \useregisterstyleandcolor\c!pagestyle\c!pagecolor
+ \registerparameter\c!pageleft}
\unexpanded\def\stopregisterpages
- {\dostoptagged
+ {\registerparameter\c!pageright
+ \dostoptagged
\endgroup}
\unexpanded\def\startregisterseewords
- {%\par % \ifhmode\crlf\fi % otherwise wrong level
- \begingroup
+ {\begingroup
\dostarttagged\t!registerpage\empty
\useregisterstyleandcolor\c!pagestyle\c!pagecolor}
@@ -876,46 +909,69 @@
% \fi}
\unexpanded\def\withregisterpagecommand#1#2#3#4%
- {\def\currentregisterpageindex{#2}%
- \iflocation
- \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]%
+ {\ifcase#3\relax
+ {\tt [entry\space not\space flushed]}%
\else
- \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}%
+ \def\currentregisterpageindex{#2}%
+ \iflocation
+ \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]%
+ \else
+ \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}%
+ \fi
\fi}
-\unexpanded\def\registeronepage#1#2#3#4% #1:processor content
- {\registerpageseparator
- \global\setconstant\c_strc_registers_page_state\plusone
- \dostarttagged\t!registerpage\empty
- \withregisterpagecommand{#1}{#2}{#3}{#4}%
- \dostoptagged}
-
-\unexpanded\def\registerpagerange#1#2#3#4#5#6#7% #1:processor content, content todo: -- configurable
- {\registerpageseparator
- \global\setconstant\c_strc_registers_page_state\plusone
- \dostarttagged\t!registerpagerange\empty
- \dostarttagged\t!registerfrompage\empty
- \withregisterpagecommand{#1}{#2}{#3}{#4}%
- \dostoptagged
- \registeronepagerangeseparator
- \dostarttagged\t!registertopage\empty
- \withregisterpagecommand{#1}{#5}{#6}{#7}%
- \dostoptagged
- \dostoptagged}
+\unexpanded\def\pushcurrentregister#1%
+ {\let\m_current_register\currentregister
+ \edef\currentregister{#1}}
+
+\unexpanded\def\popcurrentregister
+ {\let\currentregister\m_current_register}
+
+\unexpanded\def\registeronepage#1#2#3#4#5% #1:class #2:processor content
+ {\pushcurrentregister{#1}%
+ \edef\p_pagenumber{\registerparameter\c!pagenumber}%
+ \ifx\p_pagenumber\v!no\else
+ \registerpageseparator
+ \global\setconstant\c_strc_registers_page_state\plusone
+ \dostarttagged\t!registerpage\empty
+ \withregisterpagecommand{#2}{#3}{#4}{#5}%
+ \dostoptagged
+ \fi
+ \popcurrentregister}
+
+\unexpanded\def\registerpagerange#1#2#3#4#5#6#7#8% #1:class #2:processor content, content todo: -- configurable
+ {\pushcurrentregister{#1}%
+ \edef\p_pagenumber{\registerparameter\c!pagenumber}%
+ \ifx\p_pagenumber\v!no\else
+ \registerpageseparator
+ \global\setconstant\c_strc_registers_page_state\plusone
+ \dostarttagged\t!registerpagerange\empty
+ \dostarttagged\t!registerfrompage\empty
+ \withregisterpagecommand{#2}{#3}{#4}{#5}%
+ \dostoptagged
+ \registeronepagerangeseparator
+ \dostarttagged\t!registertopage\empty
+ \withregisterpagecommand{#2}{#6}{#7}{#8}%
+ \dostoptagged
+ \dostoptagged
+ \fi
+ \popcurrentregister}
-\unexpanded\def\defaultregisterentry#1#2#3#4% #1:processor #2:internal #3:seeindex #4:word
- {\def\currentregisterpageindex{#2}%
+\unexpanded\def\defaultregisterentry#1#2#3#4#5% #1:class #2:processor #3:internal #4:seeindex #5:word
+ {\pushcurrentregister{#1}%
+ \def\currentregisterpageindex{#3}%
\iflocation
- \def\currentregisterseeindex{#3}%
+ \def\currentregisterseeindex{#4}%
\ifconditional\c_strc_registers_text_interaction
- \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#1}{#4}}[internal(#2)]%
+ \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#2}{#5}}[internal(#3)]%
\else
- \doapplyregisterentrycommand{#1}{#4}%
+ \doapplyregisterentrycommand{#2}{#5}%
\fi
\else
\let\currentregisterseeindex\empty
- \doapplyregisterentrycommand{#1}{#4}%
- \fi}
+ \doapplyregisterentrycommand{#2}{#5}%
+ \fi
+ \popcurrentregister}
\unexpanded\def\doapplyregisterentrycommand#1#2% processor text
{\dostarttagged\t!registercontent\empty
@@ -935,25 +991,29 @@
\applyprocessor{#1}{#2}%
\fi\fi}
-\unexpanded\def\defaultregisterseeword#1#2#3#4#5#6% i n #3:processor #4:internal #5:seeindex #6:word
- {\registerpageseparator
+\unexpanded\def\defaultregisterseeword#1#2#3#4#5#6#7% class i n #3:processor #4:internal #5:seeindex #6:word
+ {\pushcurrentregister{#1}%
+ \ifnum#2=\plusone
+ \registerpageseparator
+ \fi
\global\setconstant\c_strc_registers_page_state\plustwo
- \def\currentregisterpageindex{#4}%
+ \def\currentregisterpageindex{#5}%
\dostarttagged\t!registersee\empty
\settrue\c_strc_registers_page_done
\iflocation
- \def\currentregisterseeindex{#5}%
+ \def\currentregisterseeindex{#6}%
\else
\let\currentregisterseeindex\empty
\fi
- \ifnum#1=\plusone
- \labeltexts\v!see{\doapplyregisterseecommand{#3}{#6}}%
- \else\ifnum#1=#2\relax
- \labeltexts\v!and{\doapplyregisterseecommand{#3}{#6}}%
+ \ifnum#2=\plusone
+ \labeltexts\v!see{\doapplyregisterseecommand{#4}{#7}}%
+ \else\ifnum#2=#3\relax
+ \labeltexts\v!and{\doapplyregisterseecommand{#4}{#7}}%
\else
- ,\space\doapplyregisterseecommand{#3}{#6}%
+ ,\space\doapplyregisterseecommand{#4}{#7}%
\fi\fi
- \dostoptagged}
+ \dostoptagged
+ \popcurrentregister}
\let\registerseeword \defaultregisterseeword
\let\registerentry \defaultregisterentry
@@ -993,18 +1053,18 @@
\setvalue{\??registersymbol\v!none}%
{\let\registerpageseparatorsymbol\empty
- \let\registeronepage \gobblefourarguments
- \let\registerpagerange \gobblesevenarguments}
+ \let\registeronepage \gobblefivearguments
+ \let\registerpagerange\gobbleeightarguments}
\setvalue{\??registersymbol 1}%
{\let\registerpageseparatorsymbol\space
- \def\registeronepage {\symbol[1]\gobblefourarguments}%
- \def\registerpagerange{\symbol[1]\gobblesevenarguments}}
+ \def\registeronepage {\symbol[1]\gobblefivearguments}%
+ \def\registerpagerange{\symbol[1]\gobbleeightarguments}}
\setvalue{\??registersymbol 2}%
{\let\registerpageseparatorsymbol\space
- \def\registeronepage {\registerpagebuttonsymbol\gobblefourarguments}%
- \def\registerpagerange{\registerpagebuttonsymbol\gobblesevenarguments}}
+ \def\registeronepage {\registerpagebuttonsymbol\gobblefivearguments}%
+ \def\registerpagerange{\registerpagebuttonsymbol\gobbleeightarguments}}
\unexpanded\def\setregisterpagerendering
{\doifelse{\registerparameter\c!pagenumber}\v!no
@@ -1016,8 +1076,8 @@
\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\gobblefivearguments}%
+ \def\registerpagerange{\registerparameter\c!symbol\gobbleeightarguments}%
\fi\fi}
\appendtoks
diff --git a/tex/context/base/mkiv/strc-ren.mkiv b/tex/context/base/mkiv/strc-ren.mkiv
index 89aa6f55a..01464ad86 100644
--- a/tex/context/base/mkiv/strc-ren.mkiv
+++ b/tex/context/base/mkiv/strc-ren.mkiv
@@ -120,7 +120,7 @@
\setheadmarking
\doresetstructureheadnumbercontent
\ifconditional\c_strc_sectioning_empty
- \setbox\b_strc_rendering_head\hbox \headreferenceattributes to \zeropoint{\strut}%
+ \setbox\b_strc_rendering_head\hpack \headreferenceattributes to \zeropoint{\strut}%
\else
\docheckheadreference
\setbox\b_strc_rendering_head\hbox \headreferenceattributes
@@ -139,7 +139,7 @@
\dosetstructureheadnumbercontent
\doresetstructureheadnumbercontent
\ifconditional\c_strc_sectioning_empty
- \setbox\b_strc_rendering_head\hbox \headreferenceattributes to \zeropoint{\strut}%
+ \setbox\b_strc_rendering_head\hpack \headreferenceattributes to \zeropoint{\strut}%
\else % = needed
\docheckheadreference
\setbox\b_strc_rendering_head\hbox \headreferenceattributes
@@ -151,7 +151,7 @@
\strc_rendering_stop_placement}
\unexpanded\def\strc_rendering_place_head_empty
- {\hbox\headreferenceattributes{\getheadsyncs}} % \hpack ?
+ {\hpack\headreferenceattributes{\getheadsyncs}}
%D \starttyping
%D \def\StretchedBox#1%
@@ -197,14 +197,13 @@
\def\strc_rendering_start_placement
{\bgroup
\setsystemmode\currenthead
- %
\strc_rendering_initialize_alternatives
\strc_rendering_initialize_dimensions
- %
\strc_rendering_initialize_line_state
\reseteverypar % needed indeed
\noindent % ipv \whitespace elders, na \forgetall !
\bgroup
+ \synctexpushline
\edef\p_aligntitle{\headparameter\c!aligntitle}%
\ifx\p_aligntitle\v!yes
\strc_rendering_initialize_hsize_local
@@ -325,7 +324,9 @@
% kind of special, we want to snap heads also according to local specs local
\setbox\b_strc_rendering_head\hbox
{\hskip\dimexpr\d_strc_rendering_local_leftoffset+\headparameter\c!margin\relax
- \box\b_strc_rendering_head}%
+ \box\b_strc_rendering_head
+ \getheadsyncs % a latelua why not in the box
+ }%
\ifgridsnapping
\applygridmethod
{\headparameter\c!grid}%
@@ -345,14 +346,14 @@
\nointerlineskip
\dosomebreak\nobreak
\fi
- \getheadsyncs
+% \getheadsyncs % a latelua why not in the box
\else
% somehow this goes ok even when we push in the margin probably because we gobble pars
% in the process of collecting index entries etc
\strut
\flushnotes % new, here since we're in par mode
\unhbox\b_strc_rendering_head
- \getheadsyncs
+ \getheadsyncs % a latelua
\ifconditional\headissomewhere
\strc_sectioning_stay_on_this_line % test case: alternative=margintext and \startparagraph ..
\else
@@ -370,6 +371,7 @@
\fi
\fi
\fi
+ \synctexpopline
\egroup
\egroup
\ifconditional\headisdisplay
@@ -528,8 +530,14 @@
\def\fakedheadnumber{\vphantom{0}} % needed for mathplus
+% \unexpanded\def\fakeheadnumbercontent
+% {\hbox to \zeropoint{\let\getheadnumber\fakedheadnumber\headnumbercontent}}
+
\unexpanded\def\fakeheadnumbercontent
- {\hbox to \zeropoint{\let\getheadnumber\fakedheadnumber\headnumbercontent}}
+ {\edef\p_hidenumber{\headparameter\c!hidenumber}%
+ \ifx\p_hidenumber\v!yes\else
+ \hbox to \zeropoint{\let\getheadnumber\fakedheadnumber\headnumbercontent}%
+ \fi}
\unexpanded\def\strc_rendering_inject_number_and_text
{\edef\p_command{\headparameter\c!command}% assumes \unexpanded definition
@@ -777,18 +785,18 @@
\startsetups[\??headrenderings:\v!bottom]
\ifconditional\headshownumber
- \setbox0\hbox {
+ \setbox\scratchboxone\hbox {
\headnumbercontent
}
- \setbox2\vbox {
+ \setbox\scratchboxtwo\vbox {
\headsetupspacing
- \advance\hsize-\wd0\relax
+ \advance\hsize-\wd\scratchboxone\relax
\headtextcontent
}
\hbox {
- \box0
+ \box\scratchboxone
\hskip\headnumberdistance
- \box2
+ \box\scratchboxtwo
}
\else
\vbox {
@@ -806,18 +814,18 @@
\startsetups[\??headrenderings:\v!top]
\ifconditional\headshownumber
- \setbox0\hbox {
+ \setbox\scratchboxone\hbox {
\headnumbercontent
}
- \setbox2\vtop {
+ \setbox\scratchboxtwo\vtop {
\headsetupspacing
- \advance\hsize-\wd0\relax
+ \advance\hsize-\wd\scratchboxone\relax
\headtextcontent
}
\hbox {
- \box0
+ \box\scratchboxone
\hskip\headnumberdistance
- \box2
+ \box\scratchboxtwo
}
\else
\vtop{
diff --git a/tex/context/base/mkiv/strc-sbe.mkiv b/tex/context/base/mkiv/strc-sbe.mkiv
index 9f1d214cf..005f03df3 100644
--- a/tex/context/base/mkiv/strc-sbe.mkiv
+++ b/tex/context/base/mkiv/strc-sbe.mkiv
@@ -45,7 +45,7 @@
\def\strc_sectionblock_define[#1][#2][#3]% singular plural settings
{\strc_sectionblock_define_normal[#1][#3]%
- \expandafter\newif\csname if#2\endcsname % obsolete
+ %\expandafter\newif\csname if#2\endcsname % obsolete
\strc_sectionblock_set_environment{#1}\empty
\setuvalue{\e!start#2}{\startsectionblock[#1]}%
\setuvalue{\e!stop #2}{\stopsectionblock}}
@@ -98,7 +98,7 @@
\clf_pushsectionblock{#1}
bookmark {\sectionblockparameter\c!bookmark}%
\relax
- \csname #1true\endcsname % obsolete
+ %\csname #1true\endcsname % obsolete
\setsystemmode\currentsectionblock
\the\everybeforesectionblock\relax
\showmessage\m!structures1\currentsectionblock}
diff --git a/tex/context/base/mkiv/strc-sec.mkiv b/tex/context/base/mkiv/strc-sec.mkiv
index 4e5115a7d..4066a1f38 100644
--- a/tex/context/base/mkiv/strc-sec.mkiv
+++ b/tex/context/base/mkiv/strc-sec.mkiv
@@ -35,6 +35,7 @@
\c!label=,
\c!coupling=,
\c!ownnumber=,
+ % \c!interaction=\v!list,
\c!sectionseparatorset=\s!default,
\c!sectionconversionset=\s!default,
\c!sectionstopper=,
@@ -53,6 +54,10 @@
\def\m_strc_references_prefix_yes{+}
\def\m_strc_references_prefix_nop{-}
+\let\currentstructurereferenceprefix\empty
+
+\installglobalmacrostack\currentstructurereferenceprefix
+
\def\strc_sectioning_set_reference_prefix
{\ifx\currentstructurereferenceprefix\empty
% nothing
@@ -64,7 +69,7 @@
\else
\setupglobalreferenceprefix[\currentstructurereferenceprefix]%
\fi\fi\fi
- \let\currentstructurereferenceprefix\referenceprefix}
+ \glet\currentstructurereferenceprefix\referenceprefix}
% why xdef ?
@@ -108,9 +113,10 @@
\def\strc_sectioning_autobookmark#1%
{\begingroup
+ % \settrialtypesetting
\the\everypreroll
\nodestostring\tempstring{#1}%
- \globallet\currentstructurebookmark\tempstring
+ \glet\currentstructurebookmark\tempstring
\endgroup}
% zeros:
@@ -150,9 +156,9 @@
\strc_sectioning_autobookmark\currentstructuretitle
\fi \fi \fi
\ifx\currentstructurelist\empty
- \globallet\currentstructurelist\currentstructuretitle
+ \glet\currentstructurelist\currentstructuretitle
\fi
- \globallet\currentstructurecoding\s!xml
+ \glet\currentstructurecoding\s!xml
\else
\ifx\currentstructureexpansion\v!yes
\xdef\currentstructuretitle {\structureparameter\c!title}%
@@ -179,9 +185,9 @@
\fi \fi
\fi
\ifx\currentstructurelist\empty
- \globallet\currentstructurelist\currentstructuretitle
+ \glet\currentstructurelist\currentstructuretitle
\fi
- \globallet\currentstructurecoding\s!tex
+ \glet\currentstructurecoding\s!tex
\fi
\setnextinternalreference
\storeinternalreference\currentstructurename{\the\locationcount}%
@@ -249,7 +255,7 @@
userdata {\detokenize{#3}}% will be converted to table at the lua end
\relax
\xdef\currentstructurelistnumber{\clf_currentsectiontolist}%
- % \currentstructuresynchronize has to be called someplace, since it introduces a node
+ % \currentstructuresynchronize has to be called someplace, since it introduces a node
\setstructuresynchronization\currentstructurelistnumber
\endgroup}
@@ -340,6 +346,9 @@
\installcommandhandler \??head {head} \??head
+\installmacrostack\currenthead
+\installmacrostack\currentheadparent
+
\setuphead [%
%\c!after=,
%\c!align=,
@@ -479,16 +488,18 @@
\to \everysetuphead
\unexpanded\def\doredefinehead#1#2% called at lua end
- {\pushmacro\currenthead
- \pushmacro\currentheadparent
+ {\push_macro_currenthead
+ \push_macro_currentheadparent
\edef\currenthead{#1}%
\edef\currentheadparent{#2}%
\the\everyredefinehead\relax
- \popmacro\currentheadparent
- \popmacro\currenthead}
+ \pop_macro_currentheadparent
+ \pop_macro_currenthead}
\let\currentnamedsection\empty
+\installmacrostack\currentnamedsection
+
\unexpanded\def\startnamedsection
{\dotripleempty\strc_sectioning_start_named_section}
@@ -577,7 +588,7 @@
\fi}
\def\strc_sectioning_setup_indeed[#1][#2][#3]%
- {\pushmacro\currenthead
+ {\push_macro_currenthead
\ifthirdargument
\edef\currenthead{#1#2}% % not used at any more in mkiv (sets now)
\setupcurrenthead[#3]%
@@ -585,7 +596,7 @@
\edef\currenthead{#1}%
\setupcurrenthead[#2]%
\fi
- \popmacro\currenthead}
+ \pop_macro_currenthead}
% we share the parameters as sections are roots of heads so eventually we can
% consider \definesection -> \definehead with one argument
@@ -638,7 +649,8 @@
{\strc_sectioning_handle{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title --
\unexpanded\def\strc_sectioning_start_named_section[#1][#2][#3]% for the moment no grouping, too annoying with page breaks
- {\pushmacro\currentnamedsection
+ {\push_macro_currentnamedsection
+ \push_macro_currentstructurereferenceprefix
\edef\currentnamedsection{#1}%
\setfalse\currentstructureown
%\globalpushmacro\currenthead % this does not work out well
@@ -659,7 +671,8 @@
\headparameter\c!aftersection
\the\everyafterhead
\resetsystemmode\currenthead
- \popmacro\currentnamedsection} % new, also here now
+ \pop_macro_currentstructurereferenceprefix
+ \pop_macro_currentnamedsection} % new, also here now
\let\dostarthead\strc_sectioning_start % used at lua end
\let\dostophead \strc_sectioning_stop % used at lua end
@@ -755,15 +768,25 @@
\setfalse\headshownumber
\fi}
+% Beware, we do need some node for anchoring marks and normally a zwnj will
+% do but it interferes so we deal with it at the \LUA\ end.
+
\newtoks\everyheadsynchronization
+% \appendtoks
+% \currentstructuresynchronize
+% \to \everyheadsynchronization
+
+\let\currentstructuresynchronize\donothing
+
\appendtoks
\currentstructuresynchronize
+ \glet\currentstructuresynchronize\donothing
\to \everyheadsynchronization
\unexpanded\def\theheadsynchonization
- {\the\everyheadsynchronization
- \currentstructuresynchronize}
+ {% no, interferes: \signalcharacter
+ \the\everyheadsynchronization}
% BEWARE: \marking[section]{my text} does not work as we use list indices instead
% so we need a 'keep track of raw set option' (or maybe a funny internal prefix)
@@ -802,6 +825,17 @@
\let\currentheadlevel \!!zerocount
\let\currentheadcounter \!!zerocount
+\let\strc_show_used\relax
+
+\installtextracker
+ {structures.showused}
+ {\let\strc_show_used\clf_showstructure}
+ {\let\strc_show_used\relax}
+
+\appendtoks
+ \strc_show_used
+\to \everystoptext
+
\unexpanded\def\placeheadtext {\dosingleempty\strc_sectioning_place_head_text } % use with care
\unexpanded\def\placeheadnumber{\dosingleempty\strc_sectioning_place_head_number} % use with care
@@ -842,6 +876,9 @@
\ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel\relax \fi
+\newtoks\everybeforesectionheadhandle
+\newtoks\everyaftersectionheadhandle
+
\def\strc_sectioning_handle#1#2#3% name data userdata (we can move #1 to the caller)
{\xdef\currenthead {#1}%
\xdef\currentheadcoupling{\sectionheadcoupling\currenthead}%
@@ -855,7 +892,7 @@
\strc_sectioning_initialize_placement
\strc_sectioning_initialize_number
%
- \flushingcolumnfloatsfalse
+ \the\everybeforesectionheadhandle
%
% todo: also mark (for header)
%
@@ -941,7 +978,9 @@
\strc_sectioning_after_nop
\fi\fi
\fi
- \flushingcolumnfloatstrue
+ %
+ \the\everyaftersectionheadhandle
+ %
\setfalse\c_strc_sectioning_ignore_page
% ignorespaces prevents spaces creeping in when after=\dontleavehmode
\dostarttagged\t!sectioncontent\empty
@@ -983,8 +1022,8 @@
\unexpanded\def\strc_rendering_place_head_section % see hidden below
{\global\setbox\b_sectioning_delayed\hpack\bgroup
\setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}%
- \hpack\headreferenceattributes{}%
- \currentstructuresynchronize
+ \hpack\headreferenceattributes{}% also does the mark
+ \theheadsynchonization
\egroup}
\unexpanded\def\strc_rendering_place_head_hidden % maybe trialtypesetting check
@@ -994,7 +1033,7 @@
{\noexpand\letgvalue{\??hiddenheadsync\currenthead}\relax
\noexpand\setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}%
\hpack\headreferenceattributes{}% otherwise no destination ... maybe tag ref as hidden and fall back on page reference
- \currentstructuresynchronize}} % and it's a node anyway
+ \theheadsynchonization}} % and it's a node anyway
\def\synchronizehead #1{\csname\??hiddenheadsync#1\endcsname}
\def\theheadreferenceattributes#1{\csname\??hiddenheadattr#1\endcsname}
@@ -1003,6 +1042,26 @@
\unexpanded\def\placerawheadtext [#1]{\getspecificstructuretitle{\thenamedheadlevel{#1}}}
\unexpanded\def\placerawheadnumber[#1]{\getfullstructurenumber{\thenamedheadlevel{#1}}}
+\unexpanded\def\repeathead[#1]%
+ {\begingroup
+ \setupinteraction[\c!state=\v!stop]%
+ \def\currenthead{#1}
+ \strc_sectioning_initialize_placement
+ \strc_sectioning_initialize_number
+ \dostarttagged\t!sectioncaption\empty
+ \let\getheadsyncs \relax
+ \def\getheadtitle {\getmarking[#1]}
+ \def\getheadnumber{\getmarking[#1\v!number]}
+ \strc_sectioning_before_yes
+ \ifconditional\headshownumber
+ \strc_rendering_place_head_number_and_text
+ \else
+ \strc_rendering_place_head_text
+ \fi
+ \dostoptagged
+ \strc_sectioning_after_yes
+ \endgroup}
+
% \setuphead[chapter][placehead=hidden]
% \chapter {test}
%
@@ -1154,7 +1213,7 @@
\else
\strc_sectioning_check_layout
\fi
- \globallet\previoushead\currenthead}
+ \glet\previoushead\currenthead}
\def\strc_sectioning_handle_page_yes
{\ifconditional\c_strc_sectioning_ignore_page
@@ -1178,7 +1237,7 @@
\fi
\global\c_strc_sectioning_preceding_level\currentheadlevel
\fi
- \globallet\previoushead\currenthead}
+ \glet\previoushead\currenthead}
\unexpanded\def\strc_sectioning_prevent_page_break#1% see strc-con
{\ifconditional\c_strc_sectioning_auto_break
diff --git a/tex/context/base/mkiv/strc-syn.mkiv b/tex/context/base/mkiv/strc-syn.mkiv
index 1fb079f04..7f71e88f5 100644
--- a/tex/context/base/mkiv/strc-syn.mkiv
+++ b/tex/context/base/mkiv/strc-syn.mkiv
@@ -114,14 +114,14 @@
\xmlstartraw
\xdef#2{#4}%
\xmlstopraw
- \globallet#3\s!xml
+ \glet#3\s!xml
\else
\ifx#1\v!yes
\xdef#2{#4}%
\else
\xdef#2{\detokenize{#4}}%
\fi
- \globallet#3\s!tex
+ \glet#3\s!tex
\fi}
%D We now use a simple list variant:
diff --git a/tex/context/base/mkiv/strc-tag.lua b/tex/context/base/mkiv/strc-tag.lua
index 649465a6a..0453640ca 100644
--- a/tex/context/base/mkiv/strc-tag.lua
+++ b/tex/context/base/mkiv/strc-tag.lua
@@ -15,7 +15,6 @@ local type, next = type, next
local insert, remove, unpack, concat, merge = table.insert, table.remove, table.unpack, table.concat, table.merge
local find, topattern, format = string.find, string.topattern, string.format
local lpegmatch, P, S, C, Cc = lpeg.match, lpeg.P, lpeg.S, lpeg.C, lpeg.Cc
-local texattribute = tex.attribute
local allocate = utilities.storage.allocate
local settings_to_hash = utilities.parsers.settings_to_hash
local setmetatableindex = table.setmetatableindex
@@ -24,34 +23,44 @@ local trace_tags = false trackers.register("structures.tags", function(v) trace
local report_tags = logs.reporter("structure","tags")
-local attributes = attributes
-local structures = structures
-local implement = interfaces.implement
-
-local a_tagged = attributes.private('tagged')
-
-local unsetvalue = attributes.unsetvalue
-local codeinjections = backends.codeinjections
-
-local taglist = allocate() -- access by attribute
-local specifications = allocate() -- access by fulltag
-local labels = allocate()
-local stack = { }
-local chain = { }
-local ids = { }
-local enabled = false
-local tagcontext = { }
-local tagpatterns = { }
-local lasttags = { }
-local stacksize = 0
-local metadata = nil -- applied to the next element
-local documentdata = { }
-
-local tags = structures.tags
-tags.taglist = taglist -- can best be hidden
-tags.labels = labels
-tags.patterns = tagpatterns
-tags.specifications = specifications
+local attributes = attributes
+local structures = structures
+local implement = interfaces.implement
+
+local a_tagged = attributes.private('tagged')
+
+local unsetvalue = attributes.unsetvalue
+local codeinjections = backends.codeinjections
+
+local texgetattribute = tex.getattribute
+local texsetattribute = tex.setattribute
+
+local taglist = allocate() -- access by attribute
+local specifications = allocate() -- access by fulltag
+local labels = allocate()
+local stack = { }
+local chain = { }
+local ids = { }
+local enabled = false
+local tagcontext = { }
+local tagpatterns = { }
+local lasttags = { }
+local stacksize = 0
+local metadata = nil -- applied to the next element
+local documentdata = { }
+local extradata = false
+
+local tags = structures.tags
+tags.taglist = taglist -- can best be hidden
+tags.labels = labels
+tags.patterns = tagpatterns
+tags.specifications = specifications
+
+function tags.current()
+ if stacksize > 0 then
+ return stack[stacksize] -- maybe copy or proxy
+ end
+end
-- Tags are internally stored as:
--
@@ -126,6 +135,7 @@ local properties = allocate { -- todo: more "record = true" to improve forma
listcontent = { pdf = "P", nature = "mixed" },
listdata = { pdf = "P", nature = "mixed" },
listpage = { pdf = "Reference", nature = "mixed" },
+ listtext = { pdf = "Span", nature = "inline" },
delimitedblock = { pdf = "BlockQuote", nature = "display" },
delimited = { pdf = "Quote", nature = "inline" },
@@ -157,9 +167,11 @@ local properties = allocate { -- todo: more "record = true" to improve forma
subformula = { pdf = "Div", nature = "display" },
link = { pdf = "Link", nature = "inline" },
+ reference = { pdf = "Span", nature = "inline" },
margintextblock = { pdf = "Span", nature = "inline" },
margintext = { pdf = "Span", nature = "inline" },
+ marginanchor = { pdf = "Span", nature = "inline" },
math = { pdf = "Div", nature = "inline" }, -- no display
mn = { pdf = "Span", nature = "mixed" },
@@ -204,6 +216,14 @@ local properties = allocate { -- todo: more "record = true" to improve forma
combinationpair = { pdf = "Span", nature = "display" },
combinationcontent = { pdf = "Span", nature = "mixed" },
combinationcaption = { pdf = "Span", nature = "mixed" },
+
+ publications = { pdf = "Div", nature = "display" },
+ publication = { pdf = "Div", nature = "mixed" },
+ pubfld = { pdf = "Span", nature = "inline" },
+
+ block = { pdf = "Div", nature = "display" },
+ userdata = { pdf = "Div", nature = "display" },
+
}
tags.properties = properties
@@ -215,7 +235,7 @@ local patterns = setmetatableindex(function(t,tag)
end)
function tags.locatedtag(tag)
- local attribute = texattribute[a_tagged]
+ local attribute = texgetattribute(a_tagged)
if attribute >= 0 then
local specification = taglist[attribute]
if specification then
@@ -235,7 +255,7 @@ function tags.locatedtag(tag)
end
function structures.atlocation(str)
- local specification = taglist[texattribute[a_tagged]]
+ local specification = taglist[texgetattribute(a_tagged)]
if specification then
if list then
local taglist = specification.taglist
@@ -287,6 +307,20 @@ function tags.getmetadata()
return documentdata or { }
end
+function tags.registerextradata(name,serializer)
+ if type(serializer) == "function" then
+ if extradata then
+ extradata[name] = serializer
+ else
+ extradata = { [name] = serializer }
+ end
+ end
+end
+
+function tags.getextradata()
+ return extradata
+end
+
function tags.start(tag,specification)
if not enabled then
codeinjections.enabletags()
@@ -349,7 +383,7 @@ function tags.start(tag,specification)
specification.metadata = documentdata
end
--
- texattribute[a_tagged] = attribute
+ texsetattribute(a_tagged,attribute)
return attribute
end
@@ -364,7 +398,7 @@ function tags.restart(attribute)
taglist[attribute] = { taglist = { unpack(chain,1,stacksize) } }
end
stack[stacksize] = attribute
- texattribute[a_tagged] = attribute
+ texsetattribute(a_tagged,attribute)
return attribute
end
@@ -374,12 +408,12 @@ function tags.stop()
end
local t = stack[stacksize]
if not t then
- -- if trace_tags then
+ if trace_tags then
report_tags("ignoring end tag, previous chain: %s",stacksize > 0 and concat(chain," ",1,stacksize) or "none")
- -- end
+ end
t = unsetvalue
end
- texattribute[a_tagged] = t
+ texsetattribute(a_tagged,t)
return t
end
diff --git a/tex/context/base/mkiv/strc-tag.mkiv b/tex/context/base/mkiv/strc-tag.mkiv
index 2ee71d67c..84e11a632 100644
--- a/tex/context/base/mkiv/strc-tag.mkiv
+++ b/tex/context/base/mkiv/strc-tag.mkiv
@@ -107,6 +107,7 @@
\def\t!listcontent {listcontent} % P
\def\t!listdata {listdata} % P
\def\t!listpage {listpage} % Reference
+\def\t!listtext {listtext} % Span
\def\t!delimitedblock {delimited} % BlockQuote
\def\t!delimited {delimited} % Quote
@@ -136,9 +137,11 @@
\def\t!subformula {subformula} % Div
\def\t!link {link} % Link
+\def\t!reference {reference} % Span
\def\t!margintext {margintext} % Span
\def\t!margintextblock {margintextblock} % Div
+\def\t!marginanchor {marginanchor} % Span
% we might opt for verbose variants so this is experimental:
@@ -162,6 +165,13 @@
\def\t!combinationcontent {combinationcontent} % Span
\def\t!combinationcaption {combinationcaption} % Span
+\def\t!publications {publications} % Span
+\def\t!publication {publication} % Span
+\def\t!pubfld {pubfld} % Span
+
+\def\t!block {block} % Div
+\def\t!userdata {userdata} % Div
+
% \setuptaglabeltext
% [en]
% [\t!document=document]
@@ -180,42 +190,51 @@
\unexpanded\def\strc_tags_set_aspect_nop#1#2{}
\unexpanded\def\strc_tags_set_aspect_yes#1#2{\clf_settagaspect{#1}{#2}} % todo: ignore when no export / also \let
+\unexpanded\def\ignoretagsinexport[#1]%
+ {\clf_ignoretagsinexport{#1}}
+
\installcorenamespace{tagging}
\installsetuponlycommandhandler \??tagging {tagging}
+% it makes no sense to have labels ... maybe some day as a last 'replace' in the export
+% which might be more efficient then ... okay, we now cannot overload but who cares
+
\unexpanded\def\strc_tags_element_start_yes{\dodoubleempty\strc_tags_element_start_yes_indeed}
\unexpanded\def\strc_tags_element_start_nop{\dodoubleempty\strc_tags_element_start_nop_indeed}
\unexpanded\def\strc_tags_element_start_yes_indeed
{\iftrialtypesetting
- \expandafter\strc_tags_element_start_nop_indeed
+ \expandafter\strc_tags_element_start_yes_indeed_nop
\else
\expandafter\strc_tags_element_start_yes_indeed_yes
\fi}
-\unexpanded\def\strc_tags_element_stop
- {\iftrialtypesetting
- \expandafter\strc_tags_element_stop_nop
- \else
- \expandafter\strc_tags_element_stop_yes
- \fi}
-
-% it makes no sense to have labels ... maybe some day as a last 'replace' in the export
-% which might be more efficient then ... okay, we now cannot overload but who cares
+\unexpanded\def\strc_tags_element_start_yes_indeed_nop[#1][#2]%
+ {}
\unexpanded\def\strc_tags_element_start_yes_indeed_yes[#1][#2]%
{\clf_starttag_u{#1}{#2}}
\unexpanded\def\strc_tags_element_stop_yes
- {\clf_stoptag}
+ {\iftrialtypesetting
+ \expandafter\strc_tags_element_stop_yes_indeed_nop
+ \else
+ \expandafter\strc_tags_element_stop_yes_indeed_yes
+ \fi}
-\unexpanded\def\strc_tags_element_start_nop_indeed[#1][#2]%
+\unexpanded\def\strc_tags_element_stop_nop
{}
-\unexpanded\def\strc_tags_element_stop_nop
+\unexpanded\def\strc_tags_element_stop_yes_indeed_nop
{}
+\unexpanded\def\strc_tags_element_stop_yes_indeed_yes
+ {\clf_stoptag}
+
+\let\strc_tags_element_start_nop_indeed\strc_tags_element_start_yes_indeed_nop
+\let\strc_tags_element_stop_nop_indeed \strc_tags_element_stop_yes_indeed_nop
+
\def\strc_tags_report_hyphen#1%
{\writestatus\m!languages{setting #1 to U+00AD}}
@@ -293,12 +312,18 @@
% \dostarttaggedchained % {tag} {detail} \??hash
% \dostarttaggednodetail % {tag}
-% \unexpanded\def\strc_tags_enable
-% {\let\dostarttagged\strc_tags_start_yes
-% \let\dostoptagged \strc_tags_stop_yes}
+\newconditional\c_strc_tags_enabled
+
+\let\dotaggedplaceholder\empty
+
+\chardef\strc_tags_placeholder_char\zerocount % "FFFC
\unexpanded\def\strc_tags_enable
- {\let\dostarttagged \strc_tags_enabled_start_detail
+ {% once enable one is toast
+ \global\settrue\c_strc_tags_enabled
+ % and gets:
+ \let\dotaggedplaceholder \strc_tags_placeholder_char
+ \let\dostarttagged \strc_tags_enabled_start_detail
\let\dostarttaggednodetail\strc_tags_enabled_start_no_detail
\let\dostarttaggedchained \strc_tags_enabled_start_chained
\let\dostoptagged \strc_tags_enabled_stop
@@ -306,12 +331,23 @@
\let\dostopignoretagging \strc_tags_stop_yes_ignore}
\unexpanded\def\strc_tags_disable
- {\let\dostarttagged \strc_tags_start_nop_detail
- \let\dostarttaggednodetail\strc_tags_start_nop_no_detail
- \let\dostarttaggedchained \strc_tags_start_nop_chained
- \let\dostoptagged \strc_tags_stop_nop
- \let\dostartignoretagging \strc_tags_start_nop_ignore
- \let\dostopignoretagging \strc_tags_stop_nop_ignore}
+ {\ifconditional\c_strc_tags_enabled
+ % so now all are artifacts
+ \let\dotaggedplaceholder \strc_tags_placeholder_char
+ \let\dostarttagged \strc_tags_start_nop_detail
+ \let\dostarttaggednodetail\strc_tags_start_nop_no_detail
+ \let\dostarttaggedchained \strc_tags_start_nop_chained
+ \let\dostoptagged \strc_tags_stop_nop_ignore
+ \else
+ % initial
+ \let\dotaggedplaceholder \empty
+ \let\dostarttagged \strc_tags_start_nop_detail
+ \let\dostarttaggednodetail\strc_tags_start_nop_no_detail
+ \let\dostarttaggedchained \strc_tags_start_nop_chained
+ \let\dostoptagged \strc_tags_stop_nop_ignore
+ \let\dostartignoretagging \strc_tags_start_nop_ignore
+ \let\dostopignoretagging \strc_tags_stop_nop_ignore
+ \fi}
% for luigi (beware: fully expandable):
@@ -468,13 +504,27 @@
%D This will only work well with sane use.
-\appendtoks
- \dostartignoretagging
-\to \everybeforepagebody
+% \appendtoks
+% {%
+% \doglobal\appendtoks
+% \strc_tags_start_yes_ignore
+% \to \everybeforepagebody
+% \doglobal\appendtoks
+% \strc_tags_stop_yes_ignore
+% \to \everyafterpagebody
+% }%
+% \to \everyenableelements
+
+% This doesn't work well either, so instead we handle the ornaments in the
+% tagging in a different way (see attr -> false code).
-\appendtoks
- \dostopignoretagging
-\to \everyafterpagebody
+% \appendtoks
+% \dostartignoretagging
+% \to \everybeforepagebody
+%
+% \appendtoks
+% \dostopignoretagging
+% \to \everyafterpagebody
% \doifelseinelement{structure:section} {yes} {no}
% \doifelseinelement{structure:chapter} {yes} {no}
diff --git a/tex/context/base/mkiv/strc-usr.lua b/tex/context/base/mkiv/strc-usr.lua
new file mode 100644
index 000000000..f121fe296
--- /dev/null
+++ b/tex/context/base/mkiv/strc-usr.lua
@@ -0,0 +1,29 @@
+if not modules then modules = { } end modules ['strc-usr'] = {
+ version = 1.000,
+ comment = "companion to strc-usr.mkiv",
+ author = "Wolfgang Schuster",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The following is copied from \type {tabl-xtb.lua} to make the userdata environment
+-- work with \LUA\ documents.
+
+local context = context
+local ctxcore = context.core
+
+local startuserdata = ctxcore.startuserdata
+local stopuserdata = ctxcore.stopuserdata
+
+local startcollecting = context.startcollecting
+local stopcollecting = context.stopcollecting
+
+function ctxcore.startuserdata(...)
+ startcollecting()
+ startuserdata(...)
+end
+
+function ctxcore.stopuserdata()
+ stopuserdata()
+ stopcollecting()
+end
diff --git a/tex/context/base/mkiv/strc-usr.mkiv b/tex/context/base/mkiv/strc-usr.mkiv
new file mode 100644
index 000000000..97b656fa0
--- /dev/null
+++ b/tex/context/base/mkiv/strc-usr.mkiv
@@ -0,0 +1,180 @@
+%D \module
+%D [ file=strc-bkm,
+%D version=2009.04.01,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Bookmarks,
+%D author=Wolfgang Schuster,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Structure Macros / Userdata}
+
+\registerctxluafile{strc-usr}{}
+
+%D It's a bit like blocks that also use buffers but more lightweight and with
+%D inplace settings.
+%D
+%D \starttyping
+%D \defineuserdata [test] [style=italic]
+%D
+%D \samplefile{klein}
+%D
+%D \startuserdata [before=\blank,after=\blank,color=red]
+%D \samplefile{greenfield}
+%D \stopuserdata
+%D
+%D \samplefile{sapolsky}
+%D
+%D \startuserdata [test]
+%D \samplefile{bryson}
+%D \stopuserdata
+%D
+%D \samplefile{jojomayer}
+%D
+%D \startuserdata [test] [before=\blank,after=\blank,color=red]
+%D \samplefile{linden}
+%D \stopuserdata
+%D
+%D \samplefile{montgomery}
+%D \stoptyping
+%D
+%D Or from \LUA:
+%D
+%D \starttyping
+%D \startluacode
+%D context.startuserdata({color="blue"})
+%D context.samplefile("klein")
+%D context.stopuserdata()
+%D \stopluacode
+%D \stoptyping
+%D
+%D An example of an alternative:
+%D
+%D \starttyping
+%D \defineuserdataalternative [epigraph] [renderingsetup=userdata:epigraph]
+%D
+%D \startsetups [userdata:epigraph]
+%D \startframedtext [location=right,frame=off,align={flushleft,broad},style=\tfx,offset=.25ex,width=.5\textwidth]
+%D \begstrut\inlinebuffer[userdata]\endstrut
+%D \hairline
+%D \wordright{\userdataparameter{author}}
+%D \stopframedtext
+%D \stopsetups
+%D
+%D \defineuserdata
+%D [epigraph]
+%D [alternative=epigraph]
+%D
+%D \startuserdata [epigraph] [author={Sean B. Carrol}]
+%D The fraction of fossil olfactory receptor genes is significantly higher in
+%D all species with full color vision. This suggests that the evolution of
+%D trichromatic vision --- which allows these primates to detect food, mates,
+%D and danger with visual cues --- has reduced their reliance on the sense of
+%D smell.
+%D \stopuserdata
+%D
+%D \startuserdata [epigraph] [author={Sean B. Carrol}]
+%D \samplefile{carrol}
+%D \stopuserdata
+%D \stoptyping
+
+\unprotect
+
+\installnamespace {userdata}
+\installnamespace {userdataalternative}
+\installnamespace {userdatarenderings}
+
+\installcommandhandler \????userdata {userdata} \????userdata
+\installcommandhandler \????userdataalternative {userdataalternative} \????userdataalternative
+
+\unexpanded\def\startuserdata
+ {\begingroup
+ \let\currentuserdata\empty
+ \doifelsenextoptionalcs\userdata_start_delayed\userdata_start_indeed}
+
+% This variant works only when the userdata instance exists while the assignment check
+% can also be used with undefined instances which falls back to the global settings.
+%
+% \def\userdata_start_delayed[#1]%
+% {\ifcsname\nameduserdatahash{\detokenize\expandafter{\normalexpanded{#1}}}\s!parent\endcsname
+% \expandafter\userdata_start_delayed_name
+% \else
+% \expandafter\userdata_start_delayed_parameters
+% \fi[#1]}
+
+\def\userdata_start_delayed[#1]%
+ {\doifelseassignmentcs{#1}%
+ \userdata_start_delayed_parameters
+ \userdata_start_delayed_name
+ [#1]}
+
+\def\userdata_start_delayed_parameters[#1]%
+ {\setupcurrentuserdata[#1]%
+ \userdata_start_indeed}
+
+\def\userdata_start_delayed_name[#1]%
+ {\edef\currentuserdata{#1}%
+ \checkuserdataparent
+ \doifelsenextoptionalcs\userdata_start_delayed_parameters\userdata_start_indeed}
+
+\def\userdata_start_indeed
+ {\grabbufferdatadirect\s!userdata{\csstring\startuserdata}{\csstring\stopuserdata}}
+
+% \unexpanded\def\stopuserdata
+% {\useuserdatastyleandcolor\c!style\c!color
+% \usealignparameter\userdataparameter
+% \edef\currentuserdataalternative{\userdataparameter\c!alternative}%
+% \ifcsname\currentuserdataalternativehash\s!parent\endcsname \else
+% \let\currentuserdataalternative\s!default
+% \fi
+% \edef\p_renderingsetup{\userdataalternativeparameter\c!renderingsetup}%
+% \directsetup\p_renderingsetup
+% \endgroup}
+
+\unexpanded\def\stopuserdata
+ {\userdataparameter\c!before % HH: moved, so we obey the outer spacing
+ \dostarttagged\t!userdata\currentuserdata % HH: added, maybe move up ?
+ \begingroup
+ \useuserdatastyleandcolor\c!style\c!color
+ \usealignparameter\userdataparameter % HH: added
+ \edef\currentuserdataalternative{\userdataparameter\c!alternative}%
+ \ifcsname\currentuserdataalternativehash\s!parent\endcsname \else
+ \let\currentuserdataalternative\s!default
+ \fi
+ \usesetupsparameter\userdataparameter
+ \edef\p_renderingsetup{\userdataalternativeparameter\c!renderingsetup}%
+ \directsetup\p_renderingsetup
+ \endgroup
+ \dostoptagged
+ \userdataparameter\c!after % HH: moved
+ \endgroup}
+
+\unexpanded\def\getuserdata
+ {\getbufferdata[\s!userdata]}
+
+\unexpanded\def\getinlineuserdata
+ {\inlinebuffer[\s!userdata]}
+
+\defineuserdataalternative
+ [\s!default]
+ [\c!renderingsetup=\????userdatarenderings:\s!default]
+
+% \startsetups[\????userdatarenderings:\s!default]
+% \userdataparameter\c!before
+% \usesetupsparameter\userdataparameter
+% \getbufferdata[\s!userdata]
+% \userdataparameter\c!after
+% \stopsetups
+
+\startsetups[\????userdatarenderings:\s!default]
+ \getuserdata
+\stopsetups
+
+\setupuserdata
+ [\c!alternative=\s!default]
+
+\protect
diff --git a/tex/context/base/mkiv/supp-box.lua b/tex/context/base/mkiv/supp-box.lua
index 40047167c..1f31f7681 100644
--- a/tex/context/base/mkiv/supp-box.lua
+++ b/tex/context/base/mkiv/supp-box.lua
@@ -20,63 +20,67 @@ local nodes = nodes
local implement = interfaces.implement
-local nodecodes = nodes.nodecodes
-
-local disc_code = nodecodes.disc
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local glue_code = nodecodes.glue
-local glyph_code = nodecodes.glyph
-
-local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
-
------ getfield = nuts.getfield
-local getnext = nuts.getnext
-local getprev = nuts.getprev
-local getboth = nuts.getboth
-local getdisc = nuts.getdisc
-local getid = nuts.getid
-local getlist = nuts.getlist
-local getattribute = nuts.getattribute
-local getbox = nuts.getbox
-local getdir = nuts.getdir
-local getwidth = nuts.getwidth
-local takebox = nuts.takebox
-
------ setfield = nuts.setfield
-local setlink = nuts.setlink
-local setboth = nuts.setboth
-local setnext = nuts.setnext
-local setbox = nuts.setbox
-local setlist = nuts.setlist
-local setdisc = nuts.setdisc
-local setwidth = nuts.setwidth
-local setheight = nuts.setheight
-local setdepth = nuts.setdepth
-
-local flush_node = nuts.flush_node
-local flush_list = nuts.flush_list
-local copy_node = nuts.copy
-local copy_list = nuts.copy_list
-local find_tail = nuts.tail
-local traverse_id = nuts.traverse_id
-local list_dimensions = nuts.dimensions
-local hpack = nuts.hpack
-
-local listtoutf = nodes.listtoutf
-
-local nodepool = nuts.pool
-local new_penalty = nodepool.penalty
-local new_hlist = nodepool.hlist
-local new_glue = nodepool.glue
-
-local setlistcolor = nodes.tracers.colors.setlist
-
-local texget = tex.get
-local texgetbox = tex.getbox
-local texsetdimen = tex.setdimen
+local nodecodes = nodes.nodecodes
+
+local disc_code = nodecodes.disc
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local glyph_code = nodecodes.glyph
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+----- getfield = nuts.getfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getboth = nuts.getboth
+local getdisc = nuts.getdisc
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getattribute = nuts.getattribute
+local getbox = nuts.getbox
+local getdirection = nuts.getdirection
+local getwidth = nuts.getwidth
+local takebox = nuts.takebox
+
+----- setfield = nuts.setfield
+local setlink = nuts.setlink
+local setboth = nuts.setboth
+local setnext = nuts.setnext
+local setbox = nuts.setbox
+local setlist = nuts.setlist
+local setdisc = nuts.setdisc
+local setwidth = nuts.setwidth
+local setheight = nuts.setheight
+local setdepth = nuts.setdepth
+local setshift = nuts.setshift
+
+local flush_node = nuts.flush_node
+local flush_list = nuts.flush_list
+local copy_node = nuts.copy
+local copy_list = nuts.copy_list
+local find_tail = nuts.tail
+local getdimensions = nuts.dimensions
+local hpack = nuts.hpack
+
+local nextdisc = nuts.traversers.disc
+local nextdir = nuts.traversers.dir
+local nexthlist = nuts.traversers.hlist
+
+local listtoutf = nodes.listtoutf
+
+local nodepool = nuts.pool
+local new_penalty = nodepool.penalty
+local new_hlist = nodepool.hlist
+local new_glue = nodepool.glue
+
+local setlistcolor = nodes.tracers.colors.setlist
+
+local texget = tex.get
+local texgetbox = tex.getbox
+local texsetdimen = tex.setdimen
local function hyphenatedlist(head,usecolor)
local current = head and tonut(head)
@@ -127,7 +131,7 @@ implement {
-- local function hyphenatedhack(head,pre)
-- pre = tonut(pre)
--- for n in traverse_id(disc_code,tonut(head)) do
+-- for n in nextdisc, tonut(head) do
-- local hyphen = getfield(n,"pre")
-- if hyphen then
-- flush_list(hyphen)
@@ -361,10 +365,12 @@ implement {
}
local function getnaturaldimensions(n)
- local w, h, d = 0, 0, 0
+ local w = 0
+ local h = 0
+ local d = 0
local l = getlist(getbox(n))
if l then
- w, h, d = list_dimensions(l)
+ w, h, d = getdimensions(l)
end
texsetdimen("lastnaturalboxwd",w)
texsetdimen("lastnaturalboxht",h)
@@ -391,10 +397,12 @@ interfaces.implement {
name = "getnaturalwd",
arguments = "integer",
actions = function(n)
- local w, h, d = 0, 0, 0
+ local w = 0
+ local h = 0
+ local d = 0
local l = getlist(getbox(n))
if l then
- w, h, d = list_dimensions(l)
+ w, h, d = getdimensions(l)
end
context("\\dimexpr%i\\scaledpoint\\relax",w)
end
@@ -416,46 +424,60 @@ interfaces.implement {
nodes.setboxtonaturalwd = setboxtonaturalwd
-local function firstdirinbox(n)
- local b = getbox(n)
- if b then
- local l = getlist(b)
- if l then
- for h in traverse_id(hlist_code,l) do
- return getdir(h)
+local doifelse = commands.doifelse
+
+do
+
+ local dirvalues = nodes.dirvalues
+ local lefttoright_code = dirvalues.lefttoright
+ local righttoleft_code = dirvalues.righttoleft
+
+ local function firstdirinbox(n)
+ local b = getbox(n)
+ if b then
+ local l = getlist(b)
+ if l then
+ for d in nextdir, l do
+ return getdirection(d)
+ end
+ for h in nexthlist, l do
+ return getdirection(h)
+ end
end
end
+ return lefttoright_code
end
-end
-nodes.firstdirinbox = firstdirinbox
+ nodes.firstdirinbox = firstdirinbox
-local doifelse = commands.doifelse
+ interfaces.implement {
+ name = "doifelserighttoleftinbox",
+ arguments = "integer",
+ actions = function(n)
+ doifelse(firstdirinbox(n) == righttoleft_code)
+ end
+ }
-interfaces.implement {
- name = "doifelserighttoleftinbox",
- arguments = "integer",
- actions = function(n)
- doifelse(firstdirinbox(n) == "TRT")
- end
-}
+end
-- new (handy for mp) .. might move to its own module
do
- local flush_list = nodes.flush_list
- local copy_list = nodes.copy_list
- local takebox = nodes.takebox
- local texsetbox = tex.setbox
-
- local new_hlist = nodes.pool.hlist
-
- local boxes = { }
- nodes.boxes = boxes
- local cache = table.setmetatableindex("table")
- local report = logs.reporter("boxes","cache")
- local trace = false
+ local nuts = nodes.nuts
+ local tonode = nuts.tonode
+ local takebox = nuts.takebox
+ local flush_list = nuts.flush_list
+ local copy_list = nuts.copy_list
+ local getwhd = nuts.getwhd
+ local setbox = nuts.setbox
+ local new_hlist = nuts.pool.hlist
+
+ local boxes = { }
+ nodes.boxes = boxes
+ local cache = table.setmetatableindex("table")
+ local report = logs.reporter("boxes","cache")
+ local trace = false
trackers.register("nodes.boxes",function(v) trace = v end)
@@ -487,7 +509,9 @@ do
if trace then
report("category %a, name %a, %s (%s)",category,name,"direct",b and "content" or "empty")
end
- return b or nil
+ if b then
+ return tonode(b)
+ end
end
function boxes.restore(category,name,box,copy)
@@ -508,11 +532,9 @@ do
if trace then
report("category %a, name %a, %s (%s)",category,name,"restore",b and "content" or "empty")
end
- texsetbox(box,b or nil)
+ setbox(box,b or nil)
end
- local getwhd = nodes.getwhd
-
function boxes.dimensions(category,name)
name = tonumber(name) or name
local b = cache[category][name]
@@ -592,13 +614,19 @@ do
actions = boxes.reset,
}
- implement {
- name = "lastlinewidth",
- actions = function()
- local head = tex.lists.page_head
- -- list dimensions returns 3 value but we take the first
- context(head and list_dimensions(getlist(find_tail(tonut(tex.lists.page_head)))) or 0)
- end
- }
-
end
+
+implement {
+ name = "lastlinewidth",
+ actions = function()
+ local head = tex.lists.page_head
+ -- list dimensions returns 3 value but we take the first
+ context(head and getdimensions(getlist(find_tail(tonut(tex.lists.page_head)))) or 0)
+ end
+}
+
+interfaces.implement {
+ name = "shiftbox",
+ arguments = { "integer", "dimension" },
+ actions = function(n,d) setshift(getbox(n),d) end,
+}
diff --git a/tex/context/base/mkiv/supp-box.mkiv b/tex/context/base/mkiv/supp-box.mkiv
index fb9cbdf5d..59e710520 100644
--- a/tex/context/base/mkiv/supp-box.mkiv
+++ b/tex/context/base/mkiv/supp-box.mkiv
@@ -15,10 +15,14 @@
\unprotect
-\registerctxluafile{supp-box}{}
+\registerctxluafile{supp-box}{optimize}
% This file is partially cleaned up.
+%D First some defaults:
+
+\fixupboxesmode\plusone
+
% handy to have
%
% \hbox to \hsize
@@ -208,8 +212,8 @@
%D \smashedvbox to ... {...}
%D \stoptyping
-\unexpanded\def\smashedhbox{\hbox\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\hbox}
-\unexpanded\def\smashedvbox{\vbox\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\vbox}
+\unexpanded\def\smashedhbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\hbox}
+\unexpanded\def\smashedvbox{\vpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\vbox}
%D First we define a helper. We use a \LUATEX\ feature in order to avoid
%D mathpalettes.
@@ -576,7 +580,7 @@
\unexpanded\def\doifelsetext#1%
{\begingroup
- \setbox\scratchbox\hbox
+ \setbox\scratchbox\hpack
{\settrialtypesetting
\ignorespaces#1\removeunwantedspaces}%
\ifzeropt\wd\scratchbox
@@ -589,7 +593,7 @@
\unexpanded\def\doiftext#1%
{\begingroup
- \setbox\scratchbox\hbox
+ \setbox\scratchbox\hpack
{\settrialtypesetting
\ignorespaces#1\removeunwantedspaces}%
\ifzeropt\wd\scratchbox
@@ -670,7 +674,7 @@
%D \afterassignment\syst_boxes_with_next_box_indeed
%D \else\ifx#2\vbox
%D \afterassignment\syst_boxes_with_next_box_indeed
-%D \else\ifx#2\normalvtop
+%D \else\ifx#2\vtop
%D \afterassignment\syst_boxes_with_next_box_indeed
%D \else\ifx#2\normalvcenter
%D \afterassignment\syst_boxes_with_next_box_indeed
@@ -730,9 +734,9 @@
%D Some well known friends, but we implement them our own
%D way. We want the macros to work in both math and text mode.
-\def\dodorlap{\hpack to \zeropoint{\box\nextbox\normalhss}\endgroup}
-\def\dodollap{\hpack to \zeropoint{\normalhss\box\nextbox}\endgroup}
-\def\dodoclap{\hpack to \zeropoint{\normalhss\box\nextbox\normalhss}\endgroup}
+\def\dodorlap{\hpack to \zeropoint{\box\nextbox\hss}\endgroup}
+\def\dodollap{\hpack to \zeropoint{\hss\box\nextbox}\endgroup}
+\def\dodoclap{\hpack to \zeropoint{\hss\box\nextbox\hss}\endgroup}
\def\dorlap{\begingroup\dowithnextboxcs\dodorlap\hbox}
\def\dollap{\begingroup\dowithnextboxcs\dodollap\hbox}
@@ -746,8 +750,8 @@
\unexpanded\def\llap{\mathortext\domathllap\dollap}
\unexpanded\def\clap{\mathortext\domathclap\doclap}
-\def\dodotlap{\vpack to \zeropoint{\normalvss\box\nextbox}\endgroup}
-\def\dodoblap{\vpack to \zeropoint{\box\nextbox\normalvss}\endgroup}
+\def\dodotlap{\vpack to \zeropoint{\vss\box\nextbox}\endgroup}
+\def\dodoblap{\vpack to \zeropoint{\box\nextbox\vss}\endgroup}
\unexpanded\def\tlap{\begingroup\dowithnextboxcs\dodotlap\vbox}
\unexpanded\def\blap{\begingroup\dowithnextboxcs\dodoblap\vbox}
@@ -1183,8 +1187,8 @@
%D complex macro than needed at first sight.
\def\dodoboundtext#1%
- {\setbox0\hbox{#1}%
- \advance\scratchdimen -\wd0
+ {\setbox\scratchboxone\hbox{#1}%
+ \advance\scratchdimen -\wd\scratchboxone
\ifdim\scratchdimen>\zeropoint\relax#1\fi}%
\def\doboundtext#1#2#3% still used?
@@ -1243,7 +1247,7 @@
\ifdim\wd\nextbox>\scratchdimen
\setbox\scratchbox\hbox{\ifdone\space#2\else#2\space\fi}%
\advance\scratchdimen -\wd\scratchbox
- \setbox0\box\nextbox
+ \setbox\scratchboxone\box\nextbox
\setbox\nextbox\vbox
{\hsize\scratchdimen
\hfuzz\maxdimen
@@ -1254,7 +1258,7 @@
\rightskip\zeropoint
\hskip\zeropoint \s!plus 1\s!fill % \hsize
\fi
- \unhcopy0}%
+ \unhcopy\scratchboxone}%
\ifdim\ht\nextbox>\strutht
\setbox\nextbox\vbox % if omitted: missing brace reported
{\splittopskip\openstrutheight
@@ -1262,7 +1266,7 @@
\setbox\nextbox\vsplit\nextbox to \strutht
\else
\doloop
- {\setbox0\vsplit\nextbox to \strutht
+ {\setbox\scratchboxone\vsplit\nextbox to \strutht
\ifdim\ht\nextbox>\strutht \else \exitloop \fi}%
\fi
\unvbox\nextbox
@@ -1304,13 +1308,13 @@
{%\dontleavehmode
\bgroup
\let\speciallimitatetext\firstoffourarguments
- \setbox0\hbox
+ \setbox\scratchboxone\hbox
{\nohyphens
\normallimitatetext{#1}{+#2}{}#4%
\normallimitatetext{#1}{-#3}{}}%
- \setbox2\hbox
+ \setbox\scratchboxtwo\hbox
{#1}%
- \ifdim\wd2<\wd0 #1\else\unhbox0\fi
+ \ifdim\wd\scratchboxtwo<\wd\scratchboxone #1\else\unhbox\scratchboxone\fi
\egroup}
\unexpanded\def\limitatetext#1#2#3% \expanded added 2003/01/16
@@ -1328,7 +1332,7 @@
%D \stoptyping
\unexpanded\def\limitatefirstline#1#2#3%
- {\hbox\bgroup\strut
+ {\hbox\bgroup\strut % \hpack
\setbox\scratchbox\hbox{\begstrut#1\endstrut}%
\ifdim\wd\scratchbox>#2\relax
\setbox\scratchbox\hbox{#3}%
@@ -1340,7 +1344,7 @@
{\unvbox\scratchbox
\global\setbox\plusone\lastbox
\global\setbox\plusone\hbox{\strut\unhbox\plusone}%
- \hbox % to #2
+ \hbox % to #2 % \hpack
{\ifx\clip\undefined
\box\plusone
\else\ifdim\wd\plusone>\hsize
@@ -1533,7 +1537,7 @@
%D a strut.
\unexpanded\def\struttedbox
- {\hbox\bgroup
+ {\hpack\bgroup
\dowithnextboxcs\syst_boxes_struttedbox_finish\hbox}
\def\syst_boxes_struttedbox_finish
@@ -1550,7 +1554,7 @@
%D equals strutdepth.
\unexpanded\def\topskippedbox
- {\hbox\bgroup\dowithnextboxcs\syst_boxes_topskippedbox_finish\hbox}
+ {\hpack\bgroup\dowithnextboxcs\syst_boxes_topskippedbox_finish\hbox}
\def\syst_boxes_topskippedbox_finish
{\edef\m_boxes_tmp{\ifdim\strutdepth=\dp\nextbox\dp\nextbox\the\dp\nextbox\fi}%
@@ -1606,22 +1610,22 @@
\unexpanded\def\centeredbox#1#% height +/-dimen width +/-dimen
{\bgroup
- \setbox0\vpack to \vsize
+ \setbox\scratchboxone\vpack to \vsize
\bgroup
\dontcomplain
\forgetall
- \setbox0\hbox{\vrule\s!width \zeropoint#1}%
- \setbox2\vbox{\hrule\s!height\zeropoint#1}%
- \advance\vsize \ht2
- \advance\hsize \wd0
+ \setbox\scratchboxone\hpack{\vrule\s!width \zeropoint#1}%
+ \setbox\scratchboxtwo\vpack{\hrule\s!height\zeropoint#1}%
+ \advance\vsize \ht\scratchboxtwo
+ \advance\hsize \wd\scratchboxone
\vpack to \vsize
\bgroup
- \vskip-\ht2
+ \vskip-\ht\scratchboxtwo
\vss
\hpack to \hsize
\bgroup
\dowithnextbox
- {\hskip-\wd0
+ {\hskip-\wd\scratchboxone
\hss
\box\nextbox
\hss
@@ -1629,14 +1633,13 @@
\vss
\egroup
\egroup
- \wd0\hsize
- \ht0\vsize
- \box0
+ \wd\scratchboxone\hsize
+ \ht\scratchboxone\vsize
+ \box\scratchboxone
\egroup}
\hbox}
-%D For those who don't want to deal with \type {\hsize}
-%D and \type {\vsize}, we have:
+%D For those who don't want to deal with \type {\hsize} and \type {\vsize}, we have:
%D
%D \starttyping
%D \centerednextbox width 2bp height 2bp
@@ -1670,9 +1673,9 @@
{\bgroup
\dowithnextbox
{\setlocalhsize
- \setbox\scratchbox\hbox{\vrule\s!width \zeropoint#1}%
+ \setbox\scratchbox\hpack{\vrule\s!width \zeropoint#1}%
\ifzeropt\wd\scratchbox\else\hsize\wd\scratchbox\fi
- \setbox\scratchbox\vbox{\hrule\s!height\zeropoint#1}%
+ \setbox\scratchbox\vpack{\hrule\s!height\zeropoint#1}%
\ifzeropt\ht\scratchbox\else\vsize\ht\scratchbox\fi
\vpack to \vsize{\vss\hpack to \hsize{\hss\box\nextbox\hss}\vss}%
\egroup}%
@@ -1764,7 +1767,7 @@
{\dorecurse\rigidcolumns
{\setbox\scratchbox\vsplit\rigidcolumnbox to \scratchdimen
\dp\scratchbox\openstrutdepth
- \setbox\scratchbox\normalvtop
+ \setbox\scratchbox\vtop
\ifalignrigidcolumns to
\ifstretchrigidcolumns\vsize\else\scratchdimen\fi
\fi
@@ -1874,21 +1877,21 @@
\unexpanded\def\convertvboxtohbox
{\makehboxofhboxes
- \setbox0\hbox{\unhbox0 \removehboxes}%
- \noindent\unhbox0\par}
+ \setbox\scratchboxone\hpack{\unhbox\scratchboxone\removehboxes}% \hpack
+ \noindent\unhbox\scratchboxone\par}
\unexpanded\def\makehboxofhboxes
- {\setbox0\emptyhbox
- \loop % \doloop { .. \exitloop .. }
- \setbox2\lastbox
- \ifhbox2
- \setbox0\hbox{\box2\unhbox0}%
+ {\setbox\scratchboxone\emptyhbox
+ \loop % \doloop { .. \exitloop .. }
+ \setbox\scratchboxtwo\lastbox
+ \ifhbox\scratchboxtwo
+ \setbox\scratchboxone\hpack{\box\scratchboxtwo\unhbox\scratchboxone}%
\repeat}
\unexpanded\def\removehboxes
- {\setbox0\lastbox
- \ifhbox0
- {\removehboxes}\unhbox0
+ {\setbox\scratchboxone\lastbox
+ \ifhbox\scratchboxone
+ {\removehboxes}\unhbox\scratchboxone
\fi}
% And one special for notes:
@@ -1947,7 +1950,7 @@
\doloop
{\setbox\hhbox\vsplit\unhhedbox to \lineheight
\ifvoid\unhhedbox
- \setbox\hhbox\hbox{\strut\hboxofvbox\hhbox}%
+ \setbox\hhbox\hbox{\strut\hboxofvbox\hhbox}% \hpack
\fi
\ht\hhbox\strutht
\dp\hhbox\strutdp
@@ -2129,7 +2132,27 @@
%D
%D \leavevmode\getbuffer
+\def\boxisempty#1%
+ {\ifdim\wd#1=\zeropoint
+ \ifdim\ht#1=\zeropoint
+ \ifdim\dp#1=\zeropoint
+ \zerocount
+ \else
+ \plusone
+ \fi
+ \else
+ \plusone
+ \fi
+ \else
+ \plusone
+ \fi}
+
\def\syst_boxes_overlay_process
+ {\ifcase\boxisempty\nextbox\else
+ \syst_boxes_overlay_process_indeed
+ \fi}
+
+\def\syst_boxes_overlay_process_indeed
{%\removeunwantedspaces % already done
\scratchdepth\dp\ifdim\dp\nextbox>\dp\processbox\nextbox\else\processbox\fi
\ifdim\ht\nextbox>\ht\processbox
@@ -2198,9 +2221,9 @@
\unexpanded\def\cbox#1#{\vbox#1\syst_boxes_lrc_process\raggedcenter}
\unexpanded\def\rbox#1#{\vbox#1\syst_boxes_lrc_process\raggedright }
-\unexpanded\def\ltop#1#{\normalvtop#1\syst_boxes_lrc_process\raggedleft }
-\unexpanded\def\ctop#1#{\normalvtop#1\syst_boxes_lrc_process\raggedcenter}
-\unexpanded\def\rtop#1#{\normalvtop#1\syst_boxes_lrc_process\raggedright }
+\unexpanded\def\ltop#1#{\vtop#1\syst_boxes_lrc_process\raggedleft }
+\unexpanded\def\ctop#1#{\vtop#1\syst_boxes_lrc_process\raggedcenter}
+\unexpanded\def\rtop#1#{\vtop#1\syst_boxes_lrc_process\raggedright }
%D The alternatives \type {\tbox} and \type {\bbox} can be used
%D to properly align boxes, like in:
@@ -2222,8 +2245,8 @@
%D
%D \getbuffer
-\unexpanded\def\tbox{\hbox\bgroup\dowithnextboxcs\syst_boxes_tbox_finish\hbox}
-\unexpanded\def\bbox{\hbox\bgroup\dowithnextboxcs\syst_boxes_bbox_finish\hbox}
+\unexpanded\def\tbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_tbox_finish\hbox}
+\unexpanded\def\bbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_bbox_finish\hbox}
\def\syst_boxes_tbox_finish
{\scratchdepth\dimexpr\ht\nextbox+\dp\nextbox-\ht\strutbox\relax
@@ -2289,7 +2312,7 @@
{\ifx\next\bgroup
\expanded{\egroup#1 to \the\sizeofbox}%
\else
- \@EA\afterassignment\@EA\docommand\@EA\scratchdimen
+ \expandafter\afterassignment\expandafter\docommand\expandafter\scratchdimen
\fi}%
\docommand}
@@ -2337,7 +2360,7 @@
\newbox\fakedboxcursor
-\setbox\fakedboxcursor\hbox
+\setbox\fakedboxcursor\hpack
{\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint}
\unexpanded\def\boxcursor % overloaded in core-vis
@@ -2723,7 +2746,7 @@
% vcenter in text, we kunnen vcenter overloaden
\unexpanded\def\halfwaybox
- {\hbox\bgroup
+ {\hpack\bgroup
\dowithnextboxcs\syst_boxes_halfwaybox_finish\hbox}
\def\syst_boxes_halfwaybox_finish
@@ -2732,7 +2755,7 @@
\egroup}
\unexpanded\def\depthonlybox
- {\vtop\bgroup
+ {\tpack\bgroup
\dowithnextboxcs\syst_boxes_depthonlybox_finish\vbox}
\def\syst_boxes_depthonlybox_finish
@@ -2747,12 +2770,7 @@
%D And even rawer:
- \let\naturalvtop \normalvtop
- \let\naturalvcenter\normalvtop
-\unexpanded\def\naturalhbox {\hbox dir TLT}
-\unexpanded\def\naturalvbox {\vbox dir TLT}
-\unexpanded\def\naturalhpack {\hpack dir TLT}
-\unexpanded\def\naturalvpack {\vpack dir TLT}
+\let\naturalvcenter\normalvtop % will go away
%D \macros
%D {vcenter}
@@ -2764,7 +2782,7 @@
\dowithnextboxcs\syst_boxes_vcenter_finish\vbox}
\def\syst_boxes_vcenter_finish
- {\hpack{\normalstartimath\normalvcenter{\box\nextbox}\normalstopimath}%
+ {\hpack{\normalstartimath\vcenter{\box\nextbox}\normalstopimath}%
\egroup}
% could be \everymathematics
@@ -2780,7 +2798,7 @@
%D A not so well unhboxable box can be made with:
\unexpanded\def\frozenhbox
- {\hbox\bgroup
+ {\hpack\bgroup
\dowithnextboxcs\syst_boxes_frozenhbox_finish\hbox}
\def\syst_boxes_frozenhbox_finish
@@ -2837,19 +2855,19 @@
\unexpanded\def\spreadhbox#1% rebuilds \hbox{<box><hss><box><hss><box>}
{\bgroup
\ifhbox#1\relax
- \setbox2\emptybox
+ \setbox\scratchboxtwo\emptybox
\unhbox#1%
\doloop
{\unpenalty\unskip\unpenalty\unskip\unpenalty\unskip
- \setbox0\lastbox
- \ifvoid0
+ \setbox\scratchboxone\lastbox
+ \ifvoid\scratchboxone
\exitloop
\else
- \setbox2\hbox
- {\ifhbox0 \spreadhbox0\else\box0\fi
- \ifvoid2 \else\hss\unhbox2\fi}%
+ \setbox\scratchboxtwo\hbox
+ {\ifhbox\scratchboxone \spreadhbox\scratchboxone\else\box\scratchboxone\fi
+ \ifvoid\scratchboxtwo \else\hss\unhbox\scratchboxtwo\fi}%
\fi}%
- \ifvoid2\else\unhbox2\fi
+ \ifvoid\scratchboxtwo\else\unhbox\scratchboxtwo\fi
\else
\box#1%
\fi
@@ -2974,6 +2992,24 @@
% \unexpanded\def\tightvbox{\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\vbox}
% \unexpanded\def\tightvtop{\dowithnextbox{\ht\nextbox\zeropoint\box\nextbox}\vtop}
+%D This one keeps dimensions and sets the shift field (and so it's more for testing
+%D than for real usage):
+
+\unexpanded\def\shiftbox{\clf_shiftbox}
+
+%D This one has been moved from a 2 decade old file. It makes something boxed
+%D sit on the baseline.
+
+\unexpanded\def\linebox
+ {\hpack\bgroup\dowithnextbox
+ {\scratchdimen\dimexpr\dimexpr\htdp\nextbox-\lineheight\relax/2+\dp\strutbox\relax
+ \setbox\nextbox\hpack{\lower\scratchdimen\box\nextbox}%
+ \ht\nextbox\ht\strutbox
+ \dp\nextbox\dp\strutbox
+ \box\nextbox
+ \egroup}
+ \hbox}
+
\protect \endinput
% a bit of test code:
diff --git a/tex/context/base/mkiv/supp-dir.mkiv b/tex/context/base/mkiv/supp-dir.mkiv
index 42a0aa37c..277f2b7ca 100644
--- a/tex/context/base/mkiv/supp-dir.mkiv
+++ b/tex/context/base/mkiv/supp-dir.mkiv
@@ -11,40 +11,44 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D We no longer have the \ETEX\ direction primitives.
-
\unprotect
-% \expanded{\defineactivecharacter \number"2000E} {\textdir TRT\relax}
-% \expanded{\defineactivecharacter \number"2000F} {\textdir TLT\relax}
+\chardef\directionlefttoright\zerocount
+\chardef\directionrighttoleft\plusone
-%D As we have less directions now we can use something
+\edef\??bdir{\ifdefined\bodydir bdir\else direction\fi}
-% \chardef\@@D@@TLT0
-% \chardef\@@D@@TRT1
-% \chardef\@@D@@RTT0
-% \chardef\@@D@@LRL1
-%
-% \def\thetextdir{\csname @@D@@\the\textdir\endcsname}
-%
-% \ifnum\thetextdir=0 L\else R\fi \textdir TRT \ifnum\thetextdir=0 L\else R\fi
+\unexpanded\edef\naturalhbox {\hbox \??bdir\directionlefttoright}
+\unexpanded\edef\naturalvbox {\vbox \??bdir\directionlefttoright}
+\unexpanded\edef\naturalvtop {\vtop \??bdir\directionlefttoright}
+\unexpanded\edef\naturalhpack {\hpack \??bdir\directionlefttoright}
+\unexpanded\edef\naturalvpack {\vpack \??bdir\directionlefttoright}
+\unexpanded\edef\naturaltpack {\tpack \??bdir\directionlefttoright}
-\unexpanded\def\showdirsinmargin
- {\inleft{\normalexpanded{\noexpand\hbox dir TLT{\ttxx[\the\pardir,\the\textdir]}}}}
+\unexpanded\edef\reversehbox {\hbox \??bdir\directionrighttoleft}
+\unexpanded\edef\reversevbox {\vbox \??bdir\directionrighttoleft}
+\unexpanded\edef\reversevtop {\vtop \??bdir\directionrighttoleft}
+\unexpanded\edef\reversehpack {\hpack \??bdir\directionrighttoleft}
+\unexpanded\edef\reversevpack {\vpack \??bdir\directionrighttoleft}
+\unexpanded\edef\reversetpack {\tpack \??bdir\directionrighttoleft}
-\bgroup
- \catcode`L=\othercatcode \gdef\istltdir#1#2#3{\if#2L0\else1\fi}
- \catcode`R=\othercatcode \gdef\istrtdir#1#2#3{\if#2R0\else1\fi}
-\egroup
+\ifdefined\bodydir
+ \let\bodydir \undefined \let\normalbodydir \undefined
+ \let\bodydirection\undefined \let\normalbodydirection\undefined
+\fi
-\def\istlttextdir{\expandafter\istltdir\the\textdir}
-\def\istrttextdir{\expandafter\istrtdir\the\textdir}
+\ifdefined\pagedir
+ \let\pagedir \undefined \let\normalpagedir \undefined
+ \let\pagedirection\undefined \let\normalpagedirection\undefined
+\fi
-\def\istltpardir {\expandafter\istltdir\the\pardir }
-\def\istrtpardir {\expandafter\istrtdir\the\pardir }
+% \expanded{\defineactivecharacter \number"2000E} {\textdirection\directionrighttoleft\relax}
+% \expanded{\defineactivecharacter \number"2000F} {\textdirection\directionlefttoright\relax}
-% \ifcase\istlttextdir Y\else N\fi
-% \ifcase\istltpardir Y\else N\fi
-% \ifcase\istltdir TRT\relax Y\else N\fi
+\def\syst_direction_string#1{\ifcase#1=\plusone r2l\else l2r\fi}
+
+\unexpanded\def\showdirsinmargin
+ {\normalexpanded{\inleft{\naturalhbox
+ {\ttxx[\syst_direction_string\pardirection,\syst_direction_string\textdirection]}}}}
\protect \endinput
diff --git a/tex/context/base/mkiv/supp-mat.mkiv b/tex/context/base/mkiv/supp-mat.mkiv
index 176233ae5..f72a0ff89 100644
--- a/tex/context/base/mkiv/supp-mat.mkiv
+++ b/tex/context/base/mkiv/supp-mat.mkiv
@@ -179,7 +179,7 @@
\popmacro\dodimensionsignal}
\unexpanded\def\nodimension#1%
- {\unskip#1\global\let\dodimensionsignal\relax}
+ {\unskip#1\glet\dodimensionsignal\relax}
%D \macros
%D {cramped}
diff --git a/tex/context/base/mkiv/symb-emj.lua b/tex/context/base/mkiv/symb-emj.lua
index 3075e0985..d6e2aebea 100644
--- a/tex/context/base/mkiv/symb-emj.lua
+++ b/tex/context/base/mkiv/symb-emj.lua
@@ -19,32 +19,27 @@ local protectglyphs = nodes.handlers.protectglyphs
local tonodes = nodes.tonodes
local currentfont = font.current
--- fast enough, no need to memoize
-
-local glyph_code = nodes.nodecodes.glyph
-local remove_node = nodes.remove
-local getid = nodes.getid
-local getnext = nodes.getnext
-local getchar = nodes.getchar
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+local remove_node = nuts.remove
+local isglyph = nuts.isglyph
local function removemodifiers(head)
+ local head = tonut(head)
local current = head
while current do
- if getid(current) == glyph_code then
- local char = getchar(current) -- using categories is too much
- if char == 0x200D or (char >= 0x1F3FB and char <= 0x1F3FF) then
- head, current = remove_node(head,current,true)
- else
- current = getnext(current)
- end
+ local char, id = isglyph(current)
+ if char and char == 0x200D or (char >= 0x1F3FB and char <= 0x1F3FF) then
+ head, current = remove_node(head,current,true)
else
current = getnext(current)
end
end
- return head
+ return tonode(head)
end
--- attributes
+-- fast enough, no need to memoize, maybe use attributes
local function checkedemoji(name,id)
local str = resolvedemoji(name)
diff --git a/tex/context/base/mkiv/symb-imp-fontawesome.mkiv b/tex/context/base/mkiv/symb-imp-fontawesome.mkiv
index 145adc46c..c638998ab 100644
--- a/tex/context/base/mkiv/symb-imp-fontawesome.mkiv
+++ b/tex/context/base/mkiv/symb-imp-fontawesome.mkiv
@@ -10,749 +10,786 @@
\definefontsynonym [FontAwesome] [file:FontAwesome.otf]
%def\FontAwesomeSymbol#1{\getglyphstyled{FontAwesome}{\utfchar{0x#1}}}
-\def\FontAwesomeSymbol#1{\getglyphstyled{FontAwesome}{\tochar{x:#1}}}
+\def\FontAwesomeSymbol#1{\getglyphstyled{FontAwesome}{\tochar{n:#1}}}
-\startsymbolset [fontawesome]
+\startsymbolset [fontawesome] [font=fontawesome]
- \definesymbol [500px] [\FontAwesomeSymbol{f26e}]
- \definesymbol [adjust] [\FontAwesomeSymbol{f042}]
- \definesymbol [adn] [\FontAwesomeSymbol{f170}]
- \definesymbol [align-center] [\FontAwesomeSymbol{f037}]
- \definesymbol [align-justify] [\FontAwesomeSymbol{f039}]
- \definesymbol [align-left] [\FontAwesomeSymbol{f036}]
- \definesymbol [align-right] [\FontAwesomeSymbol{f038}]
- \definesymbol [amazon] [\FontAwesomeSymbol{f270}]
- \definesymbol [ambulance] [\FontAwesomeSymbol{f0f9}]
- \definesymbol [american-sign-language-interpreting] [\FontAwesomeSymbol{f2a3}]
- \definesymbol [anchor] [\FontAwesomeSymbol{f13d}]
- \definesymbol [android] [\FontAwesomeSymbol{f17b}]
- \definesymbol [angellist] [\FontAwesomeSymbol{f209}]
- \definesymbol [angle-double-down] [\FontAwesomeSymbol{f103}]
- \definesymbol [angle-double-left] [\FontAwesomeSymbol{f100}]
- \definesymbol [angle-double-right] [\FontAwesomeSymbol{f101}]
- \definesymbol [angle-double-up] [\FontAwesomeSymbol{f102}]
- \definesymbol [angle-down] [\FontAwesomeSymbol{f107}]
- \definesymbol [angle-left] [\FontAwesomeSymbol{f104}]
- \definesymbol [angle-right] [\FontAwesomeSymbol{f105}]
- \definesymbol [angle-up] [\FontAwesomeSymbol{f106}]
- \definesymbol [apple] [\FontAwesomeSymbol{f179}]
- \definesymbol [archive] [\FontAwesomeSymbol{f187}]
- \definesymbol [area-chart] [\FontAwesomeSymbol{f1fe}]
- \definesymbol [arrow-circle-down] [\FontAwesomeSymbol{f0ab}]
- \definesymbol [arrow-circle-left] [\FontAwesomeSymbol{f0a8}]
- \definesymbol [arrow-circle-o-down] [\FontAwesomeSymbol{f01a}]
- \definesymbol [arrow-circle-o-left] [\FontAwesomeSymbol{f190}]
- \definesymbol [arrow-circle-o-right] [\FontAwesomeSymbol{f18e}]
- \definesymbol [arrow-circle-o-up] [\FontAwesomeSymbol{f01b}]
- \definesymbol [arrow-circle-right] [\FontAwesomeSymbol{f0a9}]
- \definesymbol [arrow-circle-up] [\FontAwesomeSymbol{f0aa}]
- \definesymbol [arrow-down] [\FontAwesomeSymbol{f063}]
- \definesymbol [arrow-left] [\FontAwesomeSymbol{f060}]
- \definesymbol [arrow-right] [\FontAwesomeSymbol{f061}]
- \definesymbol [arrow-up] [\FontAwesomeSymbol{f062}]
- \definesymbol [arrows] [\FontAwesomeSymbol{f047}]
- \definesymbol [arrows-alt] [\FontAwesomeSymbol{f0b2}]
- \definesymbol [arrows-h] [\FontAwesomeSymbol{f07e}]
- \definesymbol [arrows-v] [\FontAwesomeSymbol{f07d}]
- \definesymbol [asl-interpreting] [\FontAwesomeSymbol{f2a3}]
- \definesymbol [assistive-listening-systems] [\FontAwesomeSymbol{f2a2}]
- \definesymbol [asterisk] [\FontAwesomeSymbol{f069}]
- \definesymbol [at] [\FontAwesomeSymbol{f1fa}]
- \definesymbol [audio-description] [\FontAwesomeSymbol{f29e}]
- \definesymbol [automobile] [\FontAwesomeSymbol{f1b9}]
- \definesymbol [backward] [\FontAwesomeSymbol{f04a}]
- \definesymbol [balance-scale] [\FontAwesomeSymbol{f24e}]
- \definesymbol [ban] [\FontAwesomeSymbol{f05e}]
- \definesymbol [bank] [\FontAwesomeSymbol{f19c}]
- \definesymbol [bar-chart] [\FontAwesomeSymbol{f080}]
- \definesymbol [bar-chart-o] [\FontAwesomeSymbol{f080}]
- \definesymbol [barcode] [\FontAwesomeSymbol{f02a}]
- \definesymbol [bars] [\FontAwesomeSymbol{f0c9}]
- \definesymbol [battery-0] [\FontAwesomeSymbol{f244}]
- \definesymbol [battery-1] [\FontAwesomeSymbol{f243}]
- \definesymbol [battery-2] [\FontAwesomeSymbol{f242}]
- \definesymbol [battery-3] [\FontAwesomeSymbol{f241}]
- \definesymbol [battery-4] [\FontAwesomeSymbol{f240}]
- \definesymbol [battery-empty] [\FontAwesomeSymbol{f244}]
- \definesymbol [battery-full] [\FontAwesomeSymbol{f240}]
- \definesymbol [battery-half] [\FontAwesomeSymbol{f242}]
- \definesymbol [battery-quarter] [\FontAwesomeSymbol{f243}]
- \definesymbol [battery-three-quarters] [\FontAwesomeSymbol{f241}]
- \definesymbol [bed] [\FontAwesomeSymbol{f236}]
- \definesymbol [beer] [\FontAwesomeSymbol{f0fc}]
- \definesymbol [behance] [\FontAwesomeSymbol{f1b4}]
- \definesymbol [behance-square] [\FontAwesomeSymbol{f1b5}]
- \definesymbol [bell] [\FontAwesomeSymbol{f0f3}]
- \definesymbol [bell-o] [\FontAwesomeSymbol{f0a2}]
- \definesymbol [bell-slash] [\FontAwesomeSymbol{f1f6}]
- \definesymbol [bell-slash-o] [\FontAwesomeSymbol{f1f7}]
- \definesymbol [bicycle] [\FontAwesomeSymbol{f206}]
- \definesymbol [binoculars] [\FontAwesomeSymbol{f1e5}]
- \definesymbol [birthday-cake] [\FontAwesomeSymbol{f1fd}]
- \definesymbol [bitbucket] [\FontAwesomeSymbol{f171}]
- \definesymbol [bitbucket-square] [\FontAwesomeSymbol{f172}]
- \definesymbol [bitcoin] [\FontAwesomeSymbol{f15a}]
- \definesymbol [black-tie] [\FontAwesomeSymbol{f27e}]
- \definesymbol [blind] [\FontAwesomeSymbol{f29d}]
- \definesymbol [bluetooth] [\FontAwesomeSymbol{f293}]
- \definesymbol [bluetooth-b] [\FontAwesomeSymbol{f294}]
- \definesymbol [bold] [\FontAwesomeSymbol{f032}]
- \definesymbol [bolt] [\FontAwesomeSymbol{f0e7}]
- \definesymbol [bomb] [\FontAwesomeSymbol{f1e2}]
- \definesymbol [book] [\FontAwesomeSymbol{f02d}]
- \definesymbol [bookmark] [\FontAwesomeSymbol{f02e}]
- \definesymbol [bookmark-o] [\FontAwesomeSymbol{f097}]
- \definesymbol [braille] [\FontAwesomeSymbol{f2a1}]
- \definesymbol [briefcase] [\FontAwesomeSymbol{f0b1}]
- \definesymbol [btc] [\FontAwesomeSymbol{f15a}]
- \definesymbol [bug] [\FontAwesomeSymbol{f188}]
- \definesymbol [building] [\FontAwesomeSymbol{f1ad}]
- \definesymbol [building-o] [\FontAwesomeSymbol{f0f7}]
- \definesymbol [bullhorn] [\FontAwesomeSymbol{f0a1}]
- \definesymbol [bullseye] [\FontAwesomeSymbol{f140}]
- \definesymbol [bus] [\FontAwesomeSymbol{f207}]
- \definesymbol [buysellads] [\FontAwesomeSymbol{f20d}]
- \definesymbol [cab] [\FontAwesomeSymbol{f1ba}]
- \definesymbol [calculator] [\FontAwesomeSymbol{f1ec}]
- \definesymbol [calendar] [\FontAwesomeSymbol{f073}]
- \definesymbol [calendar-check-o] [\FontAwesomeSymbol{f274}]
- \definesymbol [calendar-minus-o] [\FontAwesomeSymbol{f272}]
- \definesymbol [calendar-o] [\FontAwesomeSymbol{f133}]
- \definesymbol [calendar-plus-o] [\FontAwesomeSymbol{f271}]
- \definesymbol [calendar-times-o] [\FontAwesomeSymbol{f273}]
- \definesymbol [camera] [\FontAwesomeSymbol{f030}]
- \definesymbol [camera-retro] [\FontAwesomeSymbol{f083}]
- \definesymbol [car] [\FontAwesomeSymbol{f1b9}]
- \definesymbol [caret-down] [\FontAwesomeSymbol{f0d7}]
- \definesymbol [caret-left] [\FontAwesomeSymbol{f0d9}]
- \definesymbol [caret-right] [\FontAwesomeSymbol{f0da}]
- \definesymbol [caret-square-o-down] [\FontAwesomeSymbol{f150}]
- \definesymbol [caret-square-o-left] [\FontAwesomeSymbol{f191}]
- \definesymbol [caret-square-o-right] [\FontAwesomeSymbol{f152}]
- \definesymbol [caret-square-o-up] [\FontAwesomeSymbol{f151}]
- \definesymbol [caret-up] [\FontAwesomeSymbol{f0d8}]
- \definesymbol [cart-arrow-down] [\FontAwesomeSymbol{f218}]
- \definesymbol [cart-plus] [\FontAwesomeSymbol{f217}]
- \definesymbol [cc] [\FontAwesomeSymbol{f20a}]
- \definesymbol [cc-amex] [\FontAwesomeSymbol{f1f3}]
- \definesymbol [cc-diners-club] [\FontAwesomeSymbol{f24c}]
- \definesymbol [cc-discover] [\FontAwesomeSymbol{f1f2}]
- \definesymbol [cc-jcb] [\FontAwesomeSymbol{f24b}]
- \definesymbol [cc-mastercard] [\FontAwesomeSymbol{f1f1}]
- \definesymbol [cc-paypal] [\FontAwesomeSymbol{f1f4}]
- \definesymbol [cc-stripe] [\FontAwesomeSymbol{f1f5}]
- \definesymbol [cc-visa] [\FontAwesomeSymbol{f1f0}]
- \definesymbol [certificate] [\FontAwesomeSymbol{f0a3}]
- \definesymbol [chain] [\FontAwesomeSymbol{f0c1}]
- \definesymbol [chain-broken] [\FontAwesomeSymbol{f127}]
- \definesymbol [check] [\FontAwesomeSymbol{f00c}]
- \definesymbol [check-circle] [\FontAwesomeSymbol{f058}]
- \definesymbol [check-circle-o] [\FontAwesomeSymbol{f05d}]
- \definesymbol [check-square] [\FontAwesomeSymbol{f14a}]
- \definesymbol [check-square-o] [\FontAwesomeSymbol{f046}]
- \definesymbol [chevron-circle-down] [\FontAwesomeSymbol{f13a}]
- \definesymbol [chevron-circle-left] [\FontAwesomeSymbol{f137}]
- \definesymbol [chevron-circle-right] [\FontAwesomeSymbol{f138}]
- \definesymbol [chevron-circle-up] [\FontAwesomeSymbol{f139}]
- \definesymbol [chevron-down] [\FontAwesomeSymbol{f078}]
- \definesymbol [chevron-left] [\FontAwesomeSymbol{f053}]
- \definesymbol [chevron-right] [\FontAwesomeSymbol{f054}]
- \definesymbol [chevron-up] [\FontAwesomeSymbol{f077}]
- \definesymbol [child] [\FontAwesomeSymbol{f1ae}]
- \definesymbol [chrome] [\FontAwesomeSymbol{f268}]
- \definesymbol [circle] [\FontAwesomeSymbol{f111}]
- \definesymbol [circle-o] [\FontAwesomeSymbol{f10c}]
- \definesymbol [circle-o-notch] [\FontAwesomeSymbol{f1ce}]
- \definesymbol [circle-thin] [\FontAwesomeSymbol{f1db}]
- \definesymbol [clipboard] [\FontAwesomeSymbol{f0ea}]
- \definesymbol [clock-o] [\FontAwesomeSymbol{f017}]
- \definesymbol [clone] [\FontAwesomeSymbol{f24d}]
- \definesymbol [close] [\FontAwesomeSymbol{f00d}]
- \definesymbol [cloud] [\FontAwesomeSymbol{f0c2}]
- \definesymbol [cloud-download] [\FontAwesomeSymbol{f0ed}]
- \definesymbol [cloud-upload] [\FontAwesomeSymbol{f0ee}]
- \definesymbol [cny] [\FontAwesomeSymbol{f157}]
- \definesymbol [code] [\FontAwesomeSymbol{f121}]
- \definesymbol [code-fork] [\FontAwesomeSymbol{f126}]
- \definesymbol [codepen] [\FontAwesomeSymbol{f1cb}]
- \definesymbol [codiepie] [\FontAwesomeSymbol{f284}]
- \definesymbol [coffee] [\FontAwesomeSymbol{f0f4}]
- \definesymbol [cog] [\FontAwesomeSymbol{f013}]
- \definesymbol [cogs] [\FontAwesomeSymbol{f085}]
- \definesymbol [columns] [\FontAwesomeSymbol{f0db}]
- \definesymbol [comment] [\FontAwesomeSymbol{f075}]
- \definesymbol [comment-o] [\FontAwesomeSymbol{f0e5}]
- \definesymbol [commenting] [\FontAwesomeSymbol{f27a}]
- \definesymbol [commenting-o] [\FontAwesomeSymbol{f27b}]
- \definesymbol [comments] [\FontAwesomeSymbol{f086}]
- \definesymbol [comments-o] [\FontAwesomeSymbol{f0e6}]
- \definesymbol [compass] [\FontAwesomeSymbol{f14e}]
- \definesymbol [compress] [\FontAwesomeSymbol{f066}]
- \definesymbol [connectdevelop] [\FontAwesomeSymbol{f20e}]
- \definesymbol [contao] [\FontAwesomeSymbol{f26d}]
- \definesymbol [copy] [\FontAwesomeSymbol{f0c5}]
- \definesymbol [copyright] [\FontAwesomeSymbol{f1f9}]
- \definesymbol [creative-commons] [\FontAwesomeSymbol{f25e}]
- \definesymbol [credit-card] [\FontAwesomeSymbol{f09d}]
- \definesymbol [credit-card-alt] [\FontAwesomeSymbol{f283}]
- \definesymbol [crop] [\FontAwesomeSymbol{f125}]
- \definesymbol [crosshairs] [\FontAwesomeSymbol{f05b}]
- \definesymbol [css3] [\FontAwesomeSymbol{f13c}]
- \definesymbol [cube] [\FontAwesomeSymbol{f1b2}]
- \definesymbol [cubes] [\FontAwesomeSymbol{f1b3}]
- \definesymbol [cut] [\FontAwesomeSymbol{f0c4}]
- \definesymbol [cutlery] [\FontAwesomeSymbol{f0f5}]
- \definesymbol [dashboard] [\FontAwesomeSymbol{f0e4}]
- \definesymbol [dashcube] [\FontAwesomeSymbol{f210}]
- \definesymbol [database] [\FontAwesomeSymbol{f1c0}]
- \definesymbol [deaf] [\FontAwesomeSymbol{f2a4}]
- \definesymbol [deafness] [\FontAwesomeSymbol{f2a4}]
- \definesymbol [dedent] [\FontAwesomeSymbol{f03b}]
- \definesymbol [delicious] [\FontAwesomeSymbol{f1a5}]
- \definesymbol [desktop] [\FontAwesomeSymbol{f108}]
- \definesymbol [deviantart] [\FontAwesomeSymbol{f1bd}]
- \definesymbol [diamond] [\FontAwesomeSymbol{f219}]
- \definesymbol [digg] [\FontAwesomeSymbol{f1a6}]
- \definesymbol [dollar] [\FontAwesomeSymbol{f155}]
- \definesymbol [dot-circle-o] [\FontAwesomeSymbol{f192}]
- \definesymbol [download] [\FontAwesomeSymbol{f019}]
- \definesymbol [dribbble] [\FontAwesomeSymbol{f17d}]
- \definesymbol [dropbox] [\FontAwesomeSymbol{f16b}]
- \definesymbol [drupal] [\FontAwesomeSymbol{f1a9}]
- \definesymbol [edge] [\FontAwesomeSymbol{f282}]
- \definesymbol [edit] [\FontAwesomeSymbol{f044}]
- \definesymbol [eject] [\FontAwesomeSymbol{f052}]
- \definesymbol [ellipsis-h] [\FontAwesomeSymbol{f141}]
- \definesymbol [ellipsis-v] [\FontAwesomeSymbol{f142}]
- \definesymbol [empire] [\FontAwesomeSymbol{f1d1}]
- \definesymbol [envelope] [\FontAwesomeSymbol{f0e0}]
- \definesymbol [envelope-o] [\FontAwesomeSymbol{f003}]
- \definesymbol [envelope-square] [\FontAwesomeSymbol{f199}]
- \definesymbol [envira] [\FontAwesomeSymbol{f299}]
- \definesymbol [eraser] [\FontAwesomeSymbol{f12d}]
- \definesymbol [eur] [\FontAwesomeSymbol{f153}]
- \definesymbol [euro] [\FontAwesomeSymbol{f153}]
- \definesymbol [exchange] [\FontAwesomeSymbol{f0ec}]
- \definesymbol [exclamation] [\FontAwesomeSymbol{f12a}]
- \definesymbol [exclamation-circle] [\FontAwesomeSymbol{f06a}]
- \definesymbol [exclamation-triangle] [\FontAwesomeSymbol{f071}]
- \definesymbol [expand] [\FontAwesomeSymbol{f065}]
- \definesymbol [expeditedssl] [\FontAwesomeSymbol{f23e}]
- \definesymbol [external-link] [\FontAwesomeSymbol{f08e}]
- \definesymbol [external-link-square] [\FontAwesomeSymbol{f14c}]
- \definesymbol [eye] [\FontAwesomeSymbol{f06e}]
- \definesymbol [eye-slash] [\FontAwesomeSymbol{f070}]
- \definesymbol [eyedropper] [\FontAwesomeSymbol{f1fb}]
- \definesymbol [fa] [\FontAwesomeSymbol{f2b4}]
- \definesymbol [facebook] [\FontAwesomeSymbol{f09a}]
- \definesymbol [facebook-f] [\FontAwesomeSymbol{f09a}]
- \definesymbol [facebook-official] [\FontAwesomeSymbol{f230}]
- \definesymbol [facebook-square] [\FontAwesomeSymbol{f082}]
- \definesymbol [fast-backward] [\FontAwesomeSymbol{f049}]
- \definesymbol [fast-forward] [\FontAwesomeSymbol{f050}]
- \definesymbol [fax] [\FontAwesomeSymbol{f1ac}]
- \definesymbol [feed] [\FontAwesomeSymbol{f09e}]
- \definesymbol [female] [\FontAwesomeSymbol{f182}]
- \definesymbol [fighter-jet] [\FontAwesomeSymbol{f0fb}]
- \definesymbol [file] [\FontAwesomeSymbol{f15b}]
- \definesymbol [file-archive-o] [\FontAwesomeSymbol{f1c6}]
- \definesymbol [file-audio-o] [\FontAwesomeSymbol{f1c7}]
- \definesymbol [file-code-o] [\FontAwesomeSymbol{f1c9}]
- \definesymbol [file-excel-o] [\FontAwesomeSymbol{f1c3}]
- \definesymbol [file-image-o] [\FontAwesomeSymbol{f1c5}]
- \definesymbol [file-movie-o] [\FontAwesomeSymbol{f1c8}]
- \definesymbol [file-o] [\FontAwesomeSymbol{f016}]
- \definesymbol [file-pdf-o] [\FontAwesomeSymbol{f1c1}]
- \definesymbol [file-photo-o] [\FontAwesomeSymbol{f1c5}]
- \definesymbol [file-picture-o] [\FontAwesomeSymbol{f1c5}]
- \definesymbol [file-powerpoint-o] [\FontAwesomeSymbol{f1c4}]
- \definesymbol [file-sound-o] [\FontAwesomeSymbol{f1c7}]
- \definesymbol [file-text] [\FontAwesomeSymbol{f15c}]
- \definesymbol [file-text-o] [\FontAwesomeSymbol{f0f6}]
- \definesymbol [file-video-o] [\FontAwesomeSymbol{f1c8}]
- \definesymbol [file-word-o] [\FontAwesomeSymbol{f1c2}]
- \definesymbol [file-zip-o] [\FontAwesomeSymbol{f1c6}]
- \definesymbol [files-o] [\FontAwesomeSymbol{f0c5}]
- \definesymbol [film] [\FontAwesomeSymbol{f008}]
- \definesymbol [filter] [\FontAwesomeSymbol{f0b0}]
- \definesymbol [fire] [\FontAwesomeSymbol{f06d}]
- \definesymbol [fire-extinguisher] [\FontAwesomeSymbol{f134}]
- \definesymbol [firefox] [\FontAwesomeSymbol{f269}]
- \definesymbol [first-order] [\FontAwesomeSymbol{f2b0}]
- \definesymbol [flag] [\FontAwesomeSymbol{f024}]
- \definesymbol [flag-checkered] [\FontAwesomeSymbol{f11e}]
- \definesymbol [flag-o] [\FontAwesomeSymbol{f11d}]
- \definesymbol [flash] [\FontAwesomeSymbol{f0e7}]
- \definesymbol [flask] [\FontAwesomeSymbol{f0c3}]
- \definesymbol [flickr] [\FontAwesomeSymbol{f16e}]
- \definesymbol [floppy-o] [\FontAwesomeSymbol{f0c7}]
- \definesymbol [folder] [\FontAwesomeSymbol{f07b}]
- \definesymbol [folder-o] [\FontAwesomeSymbol{f114}]
- \definesymbol [folder-open] [\FontAwesomeSymbol{f07c}]
- \definesymbol [folder-open-o] [\FontAwesomeSymbol{f115}]
- \definesymbol [font] [\FontAwesomeSymbol{f031}]
- \definesymbol [font-awesome] [\FontAwesomeSymbol{f2b4}]
- \definesymbol [fonticons] [\FontAwesomeSymbol{f280}]
- \definesymbol [fort-awesome] [\FontAwesomeSymbol{f286}]
- \definesymbol [forumbee] [\FontAwesomeSymbol{f211}]
- \definesymbol [forward] [\FontAwesomeSymbol{f04e}]
- \definesymbol [foursquare] [\FontAwesomeSymbol{f180}]
- \definesymbol [frown-o] [\FontAwesomeSymbol{f119}]
- \definesymbol [futbol-o] [\FontAwesomeSymbol{f1e3}]
- \definesymbol [gamepad] [\FontAwesomeSymbol{f11b}]
- \definesymbol [gavel] [\FontAwesomeSymbol{f0e3}]
- \definesymbol [gbp] [\FontAwesomeSymbol{f154}]
- \definesymbol [ge] [\FontAwesomeSymbol{f1d1}]
- \definesymbol [gear] [\FontAwesomeSymbol{f013}]
- \definesymbol [gears] [\FontAwesomeSymbol{f085}]
- \definesymbol [genderless] [\FontAwesomeSymbol{f22d}]
- \definesymbol [get-pocket] [\FontAwesomeSymbol{f265}]
- \definesymbol [gg] [\FontAwesomeSymbol{f260}]
- \definesymbol [gg-circle] [\FontAwesomeSymbol{f261}]
- \definesymbol [gift] [\FontAwesomeSymbol{f06b}]
- \definesymbol [git] [\FontAwesomeSymbol{f1d3}]
- \definesymbol [git-square] [\FontAwesomeSymbol{f1d2}]
- \definesymbol [github] [\FontAwesomeSymbol{f09b}]
- \definesymbol [github-alt] [\FontAwesomeSymbol{f113}]
- \definesymbol [github-square] [\FontAwesomeSymbol{f092}]
- \definesymbol [gitlab] [\FontAwesomeSymbol{f296}]
- \definesymbol [gittip] [\FontAwesomeSymbol{f184}]
- \definesymbol [glass] [\FontAwesomeSymbol{f000}]
- \definesymbol [glide] [\FontAwesomeSymbol{f2a5}]
- \definesymbol [glide-g] [\FontAwesomeSymbol{f2a6}]
- \definesymbol [globe] [\FontAwesomeSymbol{f0ac}]
- \definesymbol [google] [\FontAwesomeSymbol{f1a0}]
- \definesymbol [google-plus] [\FontAwesomeSymbol{f0d5}]
- \definesymbol [google-plus-circle] [\FontAwesomeSymbol{f2b3}]
- \definesymbol [google-plus-official] [\FontAwesomeSymbol{f2b3}]
- \definesymbol [google-plus-square] [\FontAwesomeSymbol{f0d4}]
- \definesymbol [google-wallet] [\FontAwesomeSymbol{f1ee}]
- \definesymbol [graduation-cap] [\FontAwesomeSymbol{f19d}]
- \definesymbol [gratipay] [\FontAwesomeSymbol{f184}]
- \definesymbol [group] [\FontAwesomeSymbol{f0c0}]
- \definesymbol [h-square] [\FontAwesomeSymbol{f0fd}]
- \definesymbol [hacker-news] [\FontAwesomeSymbol{f1d4}]
- \definesymbol [hand-grab-o] [\FontAwesomeSymbol{f255}]
- \definesymbol [hand-lizard-o] [\FontAwesomeSymbol{f258}]
- \definesymbol [hand-o-down] [\FontAwesomeSymbol{f0a7}]
- \definesymbol [hand-o-left] [\FontAwesomeSymbol{f0a5}]
- \definesymbol [hand-o-right] [\FontAwesomeSymbol{f0a4}]
- \definesymbol [hand-o-up] [\FontAwesomeSymbol{f0a6}]
- \definesymbol [hand-paper-o] [\FontAwesomeSymbol{f256}]
- \definesymbol [hand-peace-o] [\FontAwesomeSymbol{f25b}]
- \definesymbol [hand-pointer-o] [\FontAwesomeSymbol{f25a}]
- \definesymbol [hand-rock-o] [\FontAwesomeSymbol{f255}]
- \definesymbol [hand-scissors-o] [\FontAwesomeSymbol{f257}]
- \definesymbol [hand-spock-o] [\FontAwesomeSymbol{f259}]
- \definesymbol [hand-stop-o] [\FontAwesomeSymbol{f256}]
- \definesymbol [hard-of-hearing] [\FontAwesomeSymbol{f2a4}]
- \definesymbol [hashtag] [\FontAwesomeSymbol{f292}]
- \definesymbol [hdd-o] [\FontAwesomeSymbol{f0a0}]
- \definesymbol [header] [\FontAwesomeSymbol{f1dc}]
- \definesymbol [headphones] [\FontAwesomeSymbol{f025}]
- \definesymbol [heart] [\FontAwesomeSymbol{f004}]
- \definesymbol [heart-o] [\FontAwesomeSymbol{f08a}]
- \definesymbol [heartbeat] [\FontAwesomeSymbol{f21e}]
- \definesymbol [history] [\FontAwesomeSymbol{f1da}]
- \definesymbol [home] [\FontAwesomeSymbol{f015}]
- \definesymbol [hospital-o] [\FontAwesomeSymbol{f0f8}]
- \definesymbol [hotel] [\FontAwesomeSymbol{f236}]
- \definesymbol [hourglass] [\FontAwesomeSymbol{f254}]
- \definesymbol [hourglass-1] [\FontAwesomeSymbol{f251}]
- \definesymbol [hourglass-2] [\FontAwesomeSymbol{f252}]
- \definesymbol [hourglass-3] [\FontAwesomeSymbol{f253}]
- \definesymbol [hourglass-end] [\FontAwesomeSymbol{f253}]
- \definesymbol [hourglass-half] [\FontAwesomeSymbol{f252}]
- \definesymbol [hourglass-o] [\FontAwesomeSymbol{f250}]
- \definesymbol [hourglass-start] [\FontAwesomeSymbol{f251}]
- \definesymbol [houzz] [\FontAwesomeSymbol{f27c}]
- \definesymbol [html5] [\FontAwesomeSymbol{f13b}]
- \definesymbol [i-cursor] [\FontAwesomeSymbol{f246}]
- \definesymbol [ils] [\FontAwesomeSymbol{f20b}]
- \definesymbol [image] [\FontAwesomeSymbol{f03e}]
- \definesymbol [inbox] [\FontAwesomeSymbol{f01c}]
- \definesymbol [indent] [\FontAwesomeSymbol{f03c}]
- \definesymbol [industry] [\FontAwesomeSymbol{f275}]
- \definesymbol [info] [\FontAwesomeSymbol{f129}]
- \definesymbol [info-circle] [\FontAwesomeSymbol{f05a}]
- \definesymbol [inr] [\FontAwesomeSymbol{f156}]
- \definesymbol [instagram] [\FontAwesomeSymbol{f16d}]
- \definesymbol [institution] [\FontAwesomeSymbol{f19c}]
- \definesymbol [internet-explorer] [\FontAwesomeSymbol{f26b}]
- \definesymbol [intersex] [\FontAwesomeSymbol{f224}]
- \definesymbol [ioxhost] [\FontAwesomeSymbol{f208}]
- \definesymbol [italic] [\FontAwesomeSymbol{f033}]
- \definesymbol [joomla] [\FontAwesomeSymbol{f1aa}]
- \definesymbol [jpy] [\FontAwesomeSymbol{f157}]
- \definesymbol [jsfiddle] [\FontAwesomeSymbol{f1cc}]
- \definesymbol [key] [\FontAwesomeSymbol{f084}]
- \definesymbol [keyboard-o] [\FontAwesomeSymbol{f11c}]
- \definesymbol [krw] [\FontAwesomeSymbol{f159}]
- \definesymbol [language] [\FontAwesomeSymbol{f1ab}]
- \definesymbol [laptop] [\FontAwesomeSymbol{f109}]
- \definesymbol [lastfm] [\FontAwesomeSymbol{f202}]
- \definesymbol [lastfm-square] [\FontAwesomeSymbol{f203}]
- \definesymbol [leaf] [\FontAwesomeSymbol{f06c}]
- \definesymbol [leanpub] [\FontAwesomeSymbol{f212}]
- \definesymbol [legal] [\FontAwesomeSymbol{f0e3}]
- \definesymbol [lemon-o] [\FontAwesomeSymbol{f094}]
- \definesymbol [level-down] [\FontAwesomeSymbol{f149}]
- \definesymbol [level-up] [\FontAwesomeSymbol{f148}]
- \definesymbol [life-bouy] [\FontAwesomeSymbol{f1cd}]
- \definesymbol [life-buoy] [\FontAwesomeSymbol{f1cd}]
- \definesymbol [life-ring] [\FontAwesomeSymbol{f1cd}]
- \definesymbol [life-saver] [\FontAwesomeSymbol{f1cd}]
- \definesymbol [lightbulb-o] [\FontAwesomeSymbol{f0eb}]
- \definesymbol [line-chart] [\FontAwesomeSymbol{f201}]
- \definesymbol [link] [\FontAwesomeSymbol{f0c1}]
- \definesymbol [linkedin] [\FontAwesomeSymbol{f0e1}]
- \definesymbol [linkedin-square] [\FontAwesomeSymbol{f08c}]
- \definesymbol [linux] [\FontAwesomeSymbol{f17c}]
- \definesymbol [list] [\FontAwesomeSymbol{f03a}]
- \definesymbol [list-alt] [\FontAwesomeSymbol{f022}]
- \definesymbol [list-ol] [\FontAwesomeSymbol{f0cb}]
- \definesymbol [list-ul] [\FontAwesomeSymbol{f0ca}]
- \definesymbol [location-arrow] [\FontAwesomeSymbol{f124}]
- \definesymbol [lock] [\FontAwesomeSymbol{f023}]
- \definesymbol [long-arrow-down] [\FontAwesomeSymbol{f175}]
- \definesymbol [long-arrow-left] [\FontAwesomeSymbol{f177}]
- \definesymbol [long-arrow-right] [\FontAwesomeSymbol{f178}]
- \definesymbol [long-arrow-up] [\FontAwesomeSymbol{f176}]
- \definesymbol [low-vision] [\FontAwesomeSymbol{f2a8}]
- \definesymbol [magic] [\FontAwesomeSymbol{f0d0}]
- \definesymbol [magnet] [\FontAwesomeSymbol{f076}]
- \definesymbol [mail-forward] [\FontAwesomeSymbol{f064}]
- \definesymbol [mail-reply] [\FontAwesomeSymbol{f112}]
- \definesymbol [mail-reply-all] [\FontAwesomeSymbol{f122}]
- \definesymbol [male] [\FontAwesomeSymbol{f183}]
- \definesymbol [map] [\FontAwesomeSymbol{f279}]
- \definesymbol [map-marker] [\FontAwesomeSymbol{f041}]
- \definesymbol [map-o] [\FontAwesomeSymbol{f278}]
- \definesymbol [map-pin] [\FontAwesomeSymbol{f276}]
- \definesymbol [map-signs] [\FontAwesomeSymbol{f277}]
- \definesymbol [mars] [\FontAwesomeSymbol{f222}]
- \definesymbol [mars-double] [\FontAwesomeSymbol{f227}]
- \definesymbol [mars-stroke] [\FontAwesomeSymbol{f229}]
- \definesymbol [mars-stroke-h] [\FontAwesomeSymbol{f22b}]
- \definesymbol [mars-stroke-v] [\FontAwesomeSymbol{f22a}]
- \definesymbol [maxcdn] [\FontAwesomeSymbol{f136}]
- \definesymbol [meanpath] [\FontAwesomeSymbol{f20c}]
- \definesymbol [medium] [\FontAwesomeSymbol{f23a}]
- \definesymbol [medkit] [\FontAwesomeSymbol{f0fa}]
- \definesymbol [meh-o] [\FontAwesomeSymbol{f11a}]
- \definesymbol [mercury] [\FontAwesomeSymbol{f223}]
- \definesymbol [microphone] [\FontAwesomeSymbol{f130}]
- \definesymbol [microphone-slash] [\FontAwesomeSymbol{f131}]
- \definesymbol [minus] [\FontAwesomeSymbol{f068}]
- \definesymbol [minus-circle] [\FontAwesomeSymbol{f056}]
- \definesymbol [minus-square] [\FontAwesomeSymbol{f146}]
- \definesymbol [minus-square-o] [\FontAwesomeSymbol{f147}]
- \definesymbol [mixcloud] [\FontAwesomeSymbol{f289}]
- \definesymbol [mobile] [\FontAwesomeSymbol{f10b}]
- \definesymbol [mobile-phone] [\FontAwesomeSymbol{f10b}]
- \definesymbol [modx] [\FontAwesomeSymbol{f285}]
- \definesymbol [money] [\FontAwesomeSymbol{f0d6}]
- \definesymbol [moon-o] [\FontAwesomeSymbol{f186}]
- \definesymbol [mortar-board] [\FontAwesomeSymbol{f19d}]
- \definesymbol [motorcycle] [\FontAwesomeSymbol{f21c}]
- \definesymbol [mouse-pointer] [\FontAwesomeSymbol{f245}]
- \definesymbol [music] [\FontAwesomeSymbol{f001}]
- \definesymbol [navicon] [\FontAwesomeSymbol{f0c9}]
- \definesymbol [neuter] [\FontAwesomeSymbol{f22c}]
- \definesymbol [newspaper-o] [\FontAwesomeSymbol{f1ea}]
- \definesymbol [object-group] [\FontAwesomeSymbol{f247}]
- \definesymbol [object-ungroup] [\FontAwesomeSymbol{f248}]
- \definesymbol [odnoklassniki] [\FontAwesomeSymbol{f263}]
- \definesymbol [odnoklassniki-square] [\FontAwesomeSymbol{f264}]
- \definesymbol [opencart] [\FontAwesomeSymbol{f23d}]
- \definesymbol [openid] [\FontAwesomeSymbol{f19b}]
- \definesymbol [opera] [\FontAwesomeSymbol{f26a}]
- \definesymbol [optin-monster] [\FontAwesomeSymbol{f23c}]
- \definesymbol [outdent] [\FontAwesomeSymbol{f03b}]
- \definesymbol [pagelines] [\FontAwesomeSymbol{f18c}]
- \definesymbol [paint-brush] [\FontAwesomeSymbol{f1fc}]
- \definesymbol [paper-plane] [\FontAwesomeSymbol{f1d8}]
- \definesymbol [paper-plane-o] [\FontAwesomeSymbol{f1d9}]
- \definesymbol [paperclip] [\FontAwesomeSymbol{f0c6}]
- \definesymbol [paragraph] [\FontAwesomeSymbol{f1dd}]
- \definesymbol [paste] [\FontAwesomeSymbol{f0ea}]
- \definesymbol [pause] [\FontAwesomeSymbol{f04c}]
- \definesymbol [pause-circle] [\FontAwesomeSymbol{f28b}]
- \definesymbol [pause-circle-o] [\FontAwesomeSymbol{f28c}]
- \definesymbol [paw] [\FontAwesomeSymbol{f1b0}]
- \definesymbol [paypal] [\FontAwesomeSymbol{f1ed}]
- \definesymbol [pencil] [\FontAwesomeSymbol{f040}]
- \definesymbol [pencil-square] [\FontAwesomeSymbol{f14b}]
- \definesymbol [pencil-square-o] [\FontAwesomeSymbol{f044}]
- \definesymbol [percent] [\FontAwesomeSymbol{f295}]
- \definesymbol [phone] [\FontAwesomeSymbol{f095}]
- \definesymbol [phone-square] [\FontAwesomeSymbol{f098}]
- \definesymbol [photo] [\FontAwesomeSymbol{f03e}]
- \definesymbol [picture-o] [\FontAwesomeSymbol{f03e}]
- \definesymbol [pie-chart] [\FontAwesomeSymbol{f200}]
- \definesymbol [pied-piper] [\FontAwesomeSymbol{f2ae}]
- \definesymbol [pied-piper-alt] [\FontAwesomeSymbol{f1a8}]
- \definesymbol [pied-piper-pp] [\FontAwesomeSymbol{f1a7}]
- \definesymbol [pinterest] [\FontAwesomeSymbol{f0d2}]
- \definesymbol [pinterest-p] [\FontAwesomeSymbol{f231}]
- \definesymbol [pinterest-square] [\FontAwesomeSymbol{f0d3}]
- \definesymbol [plane] [\FontAwesomeSymbol{f072}]
- \definesymbol [play] [\FontAwesomeSymbol{f04b}]
- \definesymbol [play-circle] [\FontAwesomeSymbol{f144}]
- \definesymbol [play-circle-o] [\FontAwesomeSymbol{f01d}]
- \definesymbol [plug] [\FontAwesomeSymbol{f1e6}]
- \definesymbol [plus] [\FontAwesomeSymbol{f067}]
- \definesymbol [plus-circle] [\FontAwesomeSymbol{f055}]
- \definesymbol [plus-square] [\FontAwesomeSymbol{f0fe}]
- \definesymbol [plus-square-o] [\FontAwesomeSymbol{f196}]
- \definesymbol [power-off] [\FontAwesomeSymbol{f011}]
- \definesymbol [print] [\FontAwesomeSymbol{f02f}]
- \definesymbol [product-hunt] [\FontAwesomeSymbol{f288}]
- \definesymbol [puzzle-piece] [\FontAwesomeSymbol{f12e}]
- \definesymbol [qq] [\FontAwesomeSymbol{f1d6}]
- \definesymbol [qrcode] [\FontAwesomeSymbol{f029}]
- \definesymbol [question] [\FontAwesomeSymbol{f128}]
- \definesymbol [question-circle] [\FontAwesomeSymbol{f059}]
- \definesymbol [question-circle-o] [\FontAwesomeSymbol{f29c}]
- \definesymbol [quote-left] [\FontAwesomeSymbol{f10d}]
- \definesymbol [quote-right] [\FontAwesomeSymbol{f10e}]
- \definesymbol [ra] [\FontAwesomeSymbol{f1d0}]
- \definesymbol [random] [\FontAwesomeSymbol{f074}]
- \definesymbol [rebel] [\FontAwesomeSymbol{f1d0}]
- \definesymbol [recycle] [\FontAwesomeSymbol{f1b8}]
- \definesymbol [reddit] [\FontAwesomeSymbol{f1a1}]
- \definesymbol [reddit-alien] [\FontAwesomeSymbol{f281}]
- \definesymbol [reddit-square] [\FontAwesomeSymbol{f1a2}]
- \definesymbol [refresh] [\FontAwesomeSymbol{f021}]
- \definesymbol [registered] [\FontAwesomeSymbol{f25d}]
- \definesymbol [remove] [\FontAwesomeSymbol{f00d}]
- \definesymbol [renren] [\FontAwesomeSymbol{f18b}]
- \definesymbol [reorder] [\FontAwesomeSymbol{f0c9}]
- \definesymbol [repeat] [\FontAwesomeSymbol{f01e}]
- \definesymbol [reply] [\FontAwesomeSymbol{f112}]
- \definesymbol [reply-all] [\FontAwesomeSymbol{f122}]
- \definesymbol [resistance] [\FontAwesomeSymbol{f1d0}]
- \definesymbol [retweet] [\FontAwesomeSymbol{f079}]
- \definesymbol [rmb] [\FontAwesomeSymbol{f157}]
- \definesymbol [road] [\FontAwesomeSymbol{f018}]
- \definesymbol [rocket] [\FontAwesomeSymbol{f135}]
- \definesymbol [rotate-left] [\FontAwesomeSymbol{f0e2}]
- \definesymbol [rotate-right] [\FontAwesomeSymbol{f01e}]
- \definesymbol [rouble] [\FontAwesomeSymbol{f158}]
- \definesymbol [rss] [\FontAwesomeSymbol{f09e}]
- \definesymbol [rss-square] [\FontAwesomeSymbol{f143}]
- \definesymbol [rub] [\FontAwesomeSymbol{f158}]
- \definesymbol [ruble] [\FontAwesomeSymbol{f158}]
- \definesymbol [rupee] [\FontAwesomeSymbol{f156}]
- \definesymbol [safari] [\FontAwesomeSymbol{f267}]
- \definesymbol [save] [\FontAwesomeSymbol{f0c7}]
- \definesymbol [scissors] [\FontAwesomeSymbol{f0c4}]
- \definesymbol [scribd] [\FontAwesomeSymbol{f28a}]
- \definesymbol [search] [\FontAwesomeSymbol{f002}]
- \definesymbol [search-minus] [\FontAwesomeSymbol{f010}]
- \definesymbol [search-plus] [\FontAwesomeSymbol{f00e}]
- \definesymbol [sellsy] [\FontAwesomeSymbol{f213}]
- \definesymbol [send] [\FontAwesomeSymbol{f1d8}]
- \definesymbol [send-o] [\FontAwesomeSymbol{f1d9}]
- \definesymbol [server] [\FontAwesomeSymbol{f233}]
- \definesymbol [share] [\FontAwesomeSymbol{f064}]
- \definesymbol [share-alt] [\FontAwesomeSymbol{f1e0}]
- \definesymbol [share-alt-square] [\FontAwesomeSymbol{f1e1}]
- \definesymbol [share-square] [\FontAwesomeSymbol{f14d}]
- \definesymbol [share-square-o] [\FontAwesomeSymbol{f045}]
- \definesymbol [shekel] [\FontAwesomeSymbol{f20b}]
- \definesymbol [sheqel] [\FontAwesomeSymbol{f20b}]
- \definesymbol [shield] [\FontAwesomeSymbol{f132}]
- \definesymbol [ship] [\FontAwesomeSymbol{f21a}]
- \definesymbol [shirtsinbulk] [\FontAwesomeSymbol{f214}]
- \definesymbol [shopping-bag] [\FontAwesomeSymbol{f290}]
- \definesymbol [shopping-basket] [\FontAwesomeSymbol{f291}]
- \definesymbol [shopping-cart] [\FontAwesomeSymbol{f07a}]
- \definesymbol [sign-in] [\FontAwesomeSymbol{f090}]
- \definesymbol [sign-language] [\FontAwesomeSymbol{f2a7}]
- \definesymbol [sign-out] [\FontAwesomeSymbol{f08b}]
- \definesymbol [signal] [\FontAwesomeSymbol{f012}]
- \definesymbol [signing] [\FontAwesomeSymbol{f2a7}]
- \definesymbol [simplybuilt] [\FontAwesomeSymbol{f215}]
- \definesymbol [sitemap] [\FontAwesomeSymbol{f0e8}]
- \definesymbol [skyatlas] [\FontAwesomeSymbol{f216}]
- \definesymbol [skype] [\FontAwesomeSymbol{f17e}]
- \definesymbol [slack] [\FontAwesomeSymbol{f198}]
- \definesymbol [sliders] [\FontAwesomeSymbol{f1de}]
- \definesymbol [slideshare] [\FontAwesomeSymbol{f1e7}]
- \definesymbol [smile-o] [\FontAwesomeSymbol{f118}]
- \definesymbol [snapchat] [\FontAwesomeSymbol{f2ab}]
- \definesymbol [snapchat-ghost] [\FontAwesomeSymbol{f2ac}]
- \definesymbol [snapchat-square] [\FontAwesomeSymbol{f2ad}]
- \definesymbol [soccer-ball-o] [\FontAwesomeSymbol{f1e3}]
- \definesymbol [sort] [\FontAwesomeSymbol{f0dc}]
- \definesymbol [sort-alpha-asc] [\FontAwesomeSymbol{f15d}]
- \definesymbol [sort-alpha-desc] [\FontAwesomeSymbol{f15e}]
- \definesymbol [sort-amount-asc] [\FontAwesomeSymbol{f160}]
- \definesymbol [sort-amount-desc] [\FontAwesomeSymbol{f161}]
- \definesymbol [sort-asc] [\FontAwesomeSymbol{f0de}]
- \definesymbol [sort-desc] [\FontAwesomeSymbol{f0dd}]
- \definesymbol [sort-down] [\FontAwesomeSymbol{f0dd}]
- \definesymbol [sort-numeric-asc] [\FontAwesomeSymbol{f162}]
- \definesymbol [sort-numeric-desc] [\FontAwesomeSymbol{f163}]
- \definesymbol [sort-up] [\FontAwesomeSymbol{f0de}]
- \definesymbol [soundcloud] [\FontAwesomeSymbol{f1be}]
- \definesymbol [space-shuttle] [\FontAwesomeSymbol{f197}]
- \definesymbol [spinner] [\FontAwesomeSymbol{f110}]
- \definesymbol [spoon] [\FontAwesomeSymbol{f1b1}]
- \definesymbol [spotify] [\FontAwesomeSymbol{f1bc}]
- \definesymbol [square] [\FontAwesomeSymbol{f0c8}]
- \definesymbol [square-o] [\FontAwesomeSymbol{f096}]
- \definesymbol [stack-exchange] [\FontAwesomeSymbol{f18d}]
- \definesymbol [stack-overflow] [\FontAwesomeSymbol{f16c}]
- \definesymbol [star] [\FontAwesomeSymbol{f005}]
- \definesymbol [star-half] [\FontAwesomeSymbol{f089}]
- \definesymbol [star-half-empty] [\FontAwesomeSymbol{f123}]
- \definesymbol [star-half-full] [\FontAwesomeSymbol{f123}]
- \definesymbol [star-half-o] [\FontAwesomeSymbol{f123}]
- \definesymbol [star-o] [\FontAwesomeSymbol{f006}]
- \definesymbol [steam] [\FontAwesomeSymbol{f1b6}]
- \definesymbol [steam-square] [\FontAwesomeSymbol{f1b7}]
- \definesymbol [step-backward] [\FontAwesomeSymbol{f048}]
- \definesymbol [step-forward] [\FontAwesomeSymbol{f051}]
- \definesymbol [stethoscope] [\FontAwesomeSymbol{f0f1}]
- \definesymbol [sticky-note] [\FontAwesomeSymbol{f249}]
- \definesymbol [sticky-note-o] [\FontAwesomeSymbol{f24a}]
- \definesymbol [stop] [\FontAwesomeSymbol{f04d}]
- \definesymbol [stop-circle] [\FontAwesomeSymbol{f28d}]
- \definesymbol [stop-circle-o] [\FontAwesomeSymbol{f28e}]
- \definesymbol [street-view] [\FontAwesomeSymbol{f21d}]
- \definesymbol [strikethrough] [\FontAwesomeSymbol{f0cc}]
- \definesymbol [stumbleupon] [\FontAwesomeSymbol{f1a4}]
- \definesymbol [stumbleupon-circle] [\FontAwesomeSymbol{f1a3}]
- \definesymbol [subscript] [\FontAwesomeSymbol{f12c}]
- \definesymbol [subway] [\FontAwesomeSymbol{f239}]
- \definesymbol [suitcase] [\FontAwesomeSymbol{f0f2}]
- \definesymbol [sun-o] [\FontAwesomeSymbol{f185}]
- \definesymbol [superscript] [\FontAwesomeSymbol{f12b}]
- \definesymbol [support] [\FontAwesomeSymbol{f1cd}]
- \definesymbol [table] [\FontAwesomeSymbol{f0ce}]
- \definesymbol [tablet] [\FontAwesomeSymbol{f10a}]
- \definesymbol [tachometer] [\FontAwesomeSymbol{f0e4}]
- \definesymbol [tag] [\FontAwesomeSymbol{f02b}]
- \definesymbol [tags] [\FontAwesomeSymbol{f02c}]
- \definesymbol [tasks] [\FontAwesomeSymbol{f0ae}]
- \definesymbol [taxi] [\FontAwesomeSymbol{f1ba}]
- \definesymbol [television] [\FontAwesomeSymbol{f26c}]
- \definesymbol [tencent-weibo] [\FontAwesomeSymbol{f1d5}]
- \definesymbol [terminal] [\FontAwesomeSymbol{f120}]
- \definesymbol [text-height] [\FontAwesomeSymbol{f034}]
- \definesymbol [text-width] [\FontAwesomeSymbol{f035}]
- \definesymbol [th] [\FontAwesomeSymbol{f00a}]
- \definesymbol [th-large] [\FontAwesomeSymbol{f009}]
- \definesymbol [th-list] [\FontAwesomeSymbol{f00b}]
- \definesymbol [themeisle] [\FontAwesomeSymbol{f2b2}]
- \definesymbol [thumb-tack] [\FontAwesomeSymbol{f08d}]
- \definesymbol [thumbs-down] [\FontAwesomeSymbol{f165}]
- \definesymbol [thumbs-o-down] [\FontAwesomeSymbol{f088}]
- \definesymbol [thumbs-o-up] [\FontAwesomeSymbol{f087}]
- \definesymbol [thumbs-up] [\FontAwesomeSymbol{f164}]
- \definesymbol [ticket] [\FontAwesomeSymbol{f145}]
- \definesymbol [times] [\FontAwesomeSymbol{f00d}]
- \definesymbol [times-circle] [\FontAwesomeSymbol{f057}]
- \definesymbol [times-circle-o] [\FontAwesomeSymbol{f05c}]
- \definesymbol [tint] [\FontAwesomeSymbol{f043}]
- \definesymbol [toggle-down] [\FontAwesomeSymbol{f150}]
- \definesymbol [toggle-left] [\FontAwesomeSymbol{f191}]
- \definesymbol [toggle-off] [\FontAwesomeSymbol{f204}]
- \definesymbol [toggle-on] [\FontAwesomeSymbol{f205}]
- \definesymbol [toggle-right] [\FontAwesomeSymbol{f152}]
- \definesymbol [toggle-up] [\FontAwesomeSymbol{f151}]
- \definesymbol [trademark] [\FontAwesomeSymbol{f25c}]
- \definesymbol [train] [\FontAwesomeSymbol{f238}]
- \definesymbol [transgender] [\FontAwesomeSymbol{f224}]
- \definesymbol [transgender-alt] [\FontAwesomeSymbol{f225}]
- \definesymbol [trash] [\FontAwesomeSymbol{f1f8}]
- \definesymbol [trash-o] [\FontAwesomeSymbol{f014}]
- \definesymbol [tree] [\FontAwesomeSymbol{f1bb}]
- \definesymbol [trello] [\FontAwesomeSymbol{f181}]
- \definesymbol [tripadvisor] [\FontAwesomeSymbol{f262}]
- \definesymbol [trophy] [\FontAwesomeSymbol{f091}]
- \definesymbol [truck] [\FontAwesomeSymbol{f0d1}]
- \definesymbol [try] [\FontAwesomeSymbol{f195}]
- \definesymbol [tty] [\FontAwesomeSymbol{f1e4}]
- \definesymbol [tumblr] [\FontAwesomeSymbol{f173}]
- \definesymbol [tumblr-square] [\FontAwesomeSymbol{f174}]
- \definesymbol [turkish-lira] [\FontAwesomeSymbol{f195}]
- \definesymbol [tv] [\FontAwesomeSymbol{f26c}]
- \definesymbol [twitch] [\FontAwesomeSymbol{f1e8}]
- \definesymbol [twitter] [\FontAwesomeSymbol{f099}]
- \definesymbol [twitter-square] [\FontAwesomeSymbol{f081}]
- \definesymbol [umbrella] [\FontAwesomeSymbol{f0e9}]
- \definesymbol [underline] [\FontAwesomeSymbol{f0cd}]
- \definesymbol [undo] [\FontAwesomeSymbol{f0e2}]
- \definesymbol [universal-access] [\FontAwesomeSymbol{f29a}]
- \definesymbol [university] [\FontAwesomeSymbol{f19c}]
- \definesymbol [unlink] [\FontAwesomeSymbol{f127}]
- \definesymbol [unlock] [\FontAwesomeSymbol{f09c}]
- \definesymbol [unlock-alt] [\FontAwesomeSymbol{f13e}]
- \definesymbol [unsorted] [\FontAwesomeSymbol{f0dc}]
- \definesymbol [upload] [\FontAwesomeSymbol{f093}]
- \definesymbol [usb] [\FontAwesomeSymbol{f287}]
- \definesymbol [usd] [\FontAwesomeSymbol{f155}]
- \definesymbol [user] [\FontAwesomeSymbol{f007}]
- \definesymbol [user-md] [\FontAwesomeSymbol{f0f0}]
- \definesymbol [user-plus] [\FontAwesomeSymbol{f234}]
- \definesymbol [user-secret] [\FontAwesomeSymbol{f21b}]
- \definesymbol [user-times] [\FontAwesomeSymbol{f235}]
- \definesymbol [users] [\FontAwesomeSymbol{f0c0}]
- \definesymbol [venus] [\FontAwesomeSymbol{f221}]
- \definesymbol [venus-double] [\FontAwesomeSymbol{f226}]
- \definesymbol [venus-mars] [\FontAwesomeSymbol{f228}]
- \definesymbol [viacoin] [\FontAwesomeSymbol{f237}]
- \definesymbol [viadeo] [\FontAwesomeSymbol{f2a9}]
- \definesymbol [viadeo-square] [\FontAwesomeSymbol{f2aa}]
- \definesymbol [video-camera] [\FontAwesomeSymbol{f03d}]
- \definesymbol [vimeo] [\FontAwesomeSymbol{f27d}]
- \definesymbol [vimeo-square] [\FontAwesomeSymbol{f194}]
- \definesymbol [vine] [\FontAwesomeSymbol{f1ca}]
- \definesymbol [vk] [\FontAwesomeSymbol{f189}]
- \definesymbol [volume-control-phone] [\FontAwesomeSymbol{f2a0}]
- \definesymbol [volume-down] [\FontAwesomeSymbol{f027}]
- \definesymbol [volume-off] [\FontAwesomeSymbol{f026}]
- \definesymbol [volume-up] [\FontAwesomeSymbol{f028}]
- \definesymbol [warning] [\FontAwesomeSymbol{f071}]
- \definesymbol [wechat] [\FontAwesomeSymbol{f1d7}]
- \definesymbol [weibo] [\FontAwesomeSymbol{f18a}]
- \definesymbol [weixin] [\FontAwesomeSymbol{f1d7}]
- \definesymbol [whatsapp] [\FontAwesomeSymbol{f232}]
- \definesymbol [wheelchair] [\FontAwesomeSymbol{f193}]
- \definesymbol [wheelchair-alt] [\FontAwesomeSymbol{f29b}]
- \definesymbol [wifi] [\FontAwesomeSymbol{f1eb}]
- \definesymbol [wikipedia-w] [\FontAwesomeSymbol{f266}]
- \definesymbol [windows] [\FontAwesomeSymbol{f17a}]
- \definesymbol [won] [\FontAwesomeSymbol{f159}]
- \definesymbol [wordpress] [\FontAwesomeSymbol{f19a}]
- \definesymbol [wpbeginner] [\FontAwesomeSymbol{f297}]
- \definesymbol [wpforms] [\FontAwesomeSymbol{f298}]
- \definesymbol [wrench] [\FontAwesomeSymbol{f0ad}]
- \definesymbol [xing] [\FontAwesomeSymbol{f168}]
- \definesymbol [xing-square] [\FontAwesomeSymbol{f169}]
- \definesymbol [y-combinator] [\FontAwesomeSymbol{f23b}]
- \definesymbol [y-combinator-square] [\FontAwesomeSymbol{f1d4}]
- \definesymbol [yahoo] [\FontAwesomeSymbol{f19e}]
- \definesymbol [yc] [\FontAwesomeSymbol{f23b}]
- \definesymbol [yc-square] [\FontAwesomeSymbol{f1d4}]
- \definesymbol [yelp] [\FontAwesomeSymbol{f1e9}]
- \definesymbol [yen] [\FontAwesomeSymbol{f157}]
- \definesymbol [yoast] [\FontAwesomeSymbol{f2b1}]
- \definesymbol [youtube] [\FontAwesomeSymbol{f167}]
- \definesymbol [youtube-play] [\FontAwesomeSymbol{f16a}]
- \definesymbol [youtube-square] [\FontAwesomeSymbol{f166}]
+ \definesymbol [wheelchair] [\FontAwesomeSymbol{_378}]
+% \definesymbol [500px] [\FontAwesomeSymbol{f26e}]
+% \definesymbol [adjust] [\FontAwesomeSymbol{f042}]
+% \definesymbol [adn] [\FontAwesomeSymbol{f170}]
+% \definesymbol [align-center] [\FontAwesomeSymbol{f037}]
+% \definesymbol [align-justify] [\FontAwesomeSymbol{f039}]
+% \definesymbol [align-left] [\FontAwesomeSymbol{f036}]
+% \definesymbol [align-right] [\FontAwesomeSymbol{f038}]
+% \definesymbol [amazon] [\FontAwesomeSymbol{f270}]
+% \definesymbol [ambulance] [\FontAwesomeSymbol{f0f9}]
+% \definesymbol [american-sign-language-interpreting] [\FontAwesomeSymbol{f2a3}]
+% \definesymbol [anchor] [\FontAwesomeSymbol{f13d}]
+% \definesymbol [android] [\FontAwesomeSymbol{f17b}]
+% \definesymbol [angellist] [\FontAwesomeSymbol{f209}]
+% \definesymbol [angle-double-down] [\FontAwesomeSymbol{f103}]
+% \definesymbol [angle-double-left] [\FontAwesomeSymbol{f100}]
+% \definesymbol [angle-double-right] [\FontAwesomeSymbol{f101}]
+% \definesymbol [angle-double-up] [\FontAwesomeSymbol{f102}]
+% \definesymbol [angle-down] [\FontAwesomeSymbol{f107}]
+% \definesymbol [angle-left] [\FontAwesomeSymbol{f104}]
+% \definesymbol [angle-right] [\FontAwesomeSymbol{f105}]
+% \definesymbol [angle-up] [\FontAwesomeSymbol{f106}]
+% \definesymbol [apple] [\FontAwesomeSymbol{f179}]
+% \definesymbol [archive] [\FontAwesomeSymbol{f187}]
+% \definesymbol [area-chart] [\FontAwesomeSymbol{f1fe}]
+% \definesymbol [arrow-circle-down] [\FontAwesomeSymbol{f0ab}]
+% \definesymbol [arrow-circle-left] [\FontAwesomeSymbol{f0a8}]
+% \definesymbol [arrow-circle-o-down] [\FontAwesomeSymbol{f01a}]
+% \definesymbol [arrow-circle-o-left] [\FontAwesomeSymbol{f190}]
+% \definesymbol [arrow-circle-o-right] [\FontAwesomeSymbol{f18e}]
+% \definesymbol [arrow-circle-o-up] [\FontAwesomeSymbol{f01b}]
+% \definesymbol [arrow-circle-right] [\FontAwesomeSymbol{f0a9}]
+% \definesymbol [arrow-circle-up] [\FontAwesomeSymbol{f0aa}]
+% \definesymbol [arrow-down] [\FontAwesomeSymbol{f063}]
+% \definesymbol [arrow-left] [\FontAwesomeSymbol{f060}]
+% \definesymbol [arrow-right] [\FontAwesomeSymbol{f061}]
+% \definesymbol [arrow-up] [\FontAwesomeSymbol{f062}]
+% \definesymbol [arrows] [\FontAwesomeSymbol{f047}]
+% \definesymbol [arrows-alt] [\FontAwesomeSymbol{f0b2}]
+% \definesymbol [arrows-h] [\FontAwesomeSymbol{f07e}]
+% \definesymbol [arrows-v] [\FontAwesomeSymbol{f07d}]
+% \definesymbol [asl-interpreting] [\FontAwesomeSymbol{f2a3}]
+% \definesymbol [assistive-listening-systems] [\FontAwesomeSymbol{f2a2}]
+% \definesymbol [asterisk] [\FontAwesomeSymbol{f069}]
+% \definesymbol [at] [\FontAwesomeSymbol{f1fa}]
+% \definesymbol [audio-description] [\FontAwesomeSymbol{f29e}]
+% \definesymbol [automobile] [\FontAwesomeSymbol{f1b9}]
+% \definesymbol [backward] [\FontAwesomeSymbol{f04a}]
+% \definesymbol [balance-scale] [\FontAwesomeSymbol{f24e}]
+% \definesymbol [ban] [\FontAwesomeSymbol{f05e}]
+% \definesymbol [bank] [\FontAwesomeSymbol{f19c}]
+% \definesymbol [bar-chart] [\FontAwesomeSymbol{f080}]
+% \definesymbol [bar-chart-o] [\FontAwesomeSymbol{f080}]
+% \definesymbol [barcode] [\FontAwesomeSymbol{f02a}]
+% \definesymbol [bars] [\FontAwesomeSymbol{f0c9}]
+% \definesymbol [battery-0] [\FontAwesomeSymbol{f244}]
+% \definesymbol [battery-1] [\FontAwesomeSymbol{f243}]
+% \definesymbol [battery-2] [\FontAwesomeSymbol{f242}]
+% \definesymbol [battery-3] [\FontAwesomeSymbol{f241}]
+% \definesymbol [battery-4] [\FontAwesomeSymbol{f240}]
+% \definesymbol [battery-empty] [\FontAwesomeSymbol{f244}]
+% \definesymbol [battery-full] [\FontAwesomeSymbol{f240}]
+% \definesymbol [battery-half] [\FontAwesomeSymbol{f242}]
+% \definesymbol [battery-quarter] [\FontAwesomeSymbol{f243}]
+% \definesymbol [battery-three-quarters] [\FontAwesomeSymbol{f241}]
+% \definesymbol [bed] [\FontAwesomeSymbol{f236}]
+% \definesymbol [beer] [\FontAwesomeSymbol{f0fc}]
+% \definesymbol [behance] [\FontAwesomeSymbol{f1b4}]
+% \definesymbol [behance-square] [\FontAwesomeSymbol{f1b5}]
+% \definesymbol [bell] [\FontAwesomeSymbol{f0f3}]
+% \definesymbol [bell-o] [\FontAwesomeSymbol{f0a2}]
+% \definesymbol [bell-slash] [\FontAwesomeSymbol{f1f6}]
+% \definesymbol [bell-slash-o] [\FontAwesomeSymbol{f1f7}]
+% \definesymbol [bicycle] [\FontAwesomeSymbol{f206}]
+% \definesymbol [binoculars] [\FontAwesomeSymbol{f1e5}]
+% \definesymbol [birthday-cake] [\FontAwesomeSymbol{f1fd}]
+% \definesymbol [bitbucket] [\FontAwesomeSymbol{f171}]
+% \definesymbol [bitbucket-square] [\FontAwesomeSymbol{f172}]
+% \definesymbol [bitcoin] [\FontAwesomeSymbol{f15a}]
+% \definesymbol [black-tie] [\FontAwesomeSymbol{f27e}]
+% \definesymbol [blind] [\FontAwesomeSymbol{f29d}]
+% \definesymbol [bluetooth] [\FontAwesomeSymbol{f293}]
+% \definesymbol [bluetooth-b] [\FontAwesomeSymbol{f294}]
+% \definesymbol [bold] [\FontAwesomeSymbol{f032}]
+% \definesymbol [bolt] [\FontAwesomeSymbol{f0e7}]
+% \definesymbol [bomb] [\FontAwesomeSymbol{f1e2}]
+% \definesymbol [book] [\FontAwesomeSymbol{f02d}]
+% \definesymbol [bookmark] [\FontAwesomeSymbol{f02e}]
+% \definesymbol [bookmark-o] [\FontAwesomeSymbol{f097}]
+% \definesymbol [braille] [\FontAwesomeSymbol{f2a1}]
+% \definesymbol [briefcase] [\FontAwesomeSymbol{f0b1}]
+% \definesymbol [btc] [\FontAwesomeSymbol{f15a}]
+% \definesymbol [bug] [\FontAwesomeSymbol{f188}]
+% \definesymbol [building] [\FontAwesomeSymbol{f1ad}]
+% \definesymbol [building-o] [\FontAwesomeSymbol{f0f7}]
+% \definesymbol [bullhorn] [\FontAwesomeSymbol{f0a1}]
+% \definesymbol [bullseye] [\FontAwesomeSymbol{f140}]
+% \definesymbol [bus] [\FontAwesomeSymbol{f207}]
+% \definesymbol [buysellads] [\FontAwesomeSymbol{f20d}]
+% \definesymbol [cab] [\FontAwesomeSymbol{f1ba}]
+% \definesymbol [calculator] [\FontAwesomeSymbol{f1ec}]
+% \definesymbol [calendar] [\FontAwesomeSymbol{f073}]
+% \definesymbol [calendar-check-o] [\FontAwesomeSymbol{f274}]
+% \definesymbol [calendar-minus-o] [\FontAwesomeSymbol{f272}]
+% \definesymbol [calendar-o] [\FontAwesomeSymbol{f133}]
+% \definesymbol [calendar-plus-o] [\FontAwesomeSymbol{f271}]
+% \definesymbol [calendar-times-o] [\FontAwesomeSymbol{f273}]
+% \definesymbol [camera] [\FontAwesomeSymbol{f030}]
+% \definesymbol [camera-retro] [\FontAwesomeSymbol{f083}]
+% \definesymbol [car] [\FontAwesomeSymbol{f1b9}]
+% \definesymbol [caret-down] [\FontAwesomeSymbol{f0d7}]
+% \definesymbol [caret-left] [\FontAwesomeSymbol{f0d9}]
+% \definesymbol [caret-right] [\FontAwesomeSymbol{f0da}]
+% \definesymbol [caret-square-o-down] [\FontAwesomeSymbol{f150}]
+% \definesymbol [caret-square-o-left] [\FontAwesomeSymbol{f191}]
+% \definesymbol [caret-square-o-right] [\FontAwesomeSymbol{f152}]
+% \definesymbol [caret-square-o-up] [\FontAwesomeSymbol{f151}]
+% \definesymbol [caret-up] [\FontAwesomeSymbol{f0d8}]
+% \definesymbol [cart-arrow-down] [\FontAwesomeSymbol{f218}]
+% \definesymbol [cart-plus] [\FontAwesomeSymbol{f217}]
+% \definesymbol [cc] [\FontAwesomeSymbol{f20a}]
+% \definesymbol [cc-amex] [\FontAwesomeSymbol{f1f3}]
+% \definesymbol [cc-diners-club] [\FontAwesomeSymbol{f24c}]
+% \definesymbol [cc-discover] [\FontAwesomeSymbol{f1f2}]
+% \definesymbol [cc-jcb] [\FontAwesomeSymbol{f24b}]
+% \definesymbol [cc-mastercard] [\FontAwesomeSymbol{f1f1}]
+% \definesymbol [cc-paypal] [\FontAwesomeSymbol{f1f4}]
+% \definesymbol [cc-stripe] [\FontAwesomeSymbol{f1f5}]
+% \definesymbol [cc-visa] [\FontAwesomeSymbol{f1f0}]
+% \definesymbol [certificate] [\FontAwesomeSymbol{f0a3}]
+% \definesymbol [chain] [\FontAwesomeSymbol{f0c1}]
+% \definesymbol [chain-broken] [\FontAwesomeSymbol{f127}]
+% \definesymbol [check] [\FontAwesomeSymbol{f00c}]
+% \definesymbol [check-circle] [\FontAwesomeSymbol{f058}]
+% \definesymbol [check-circle-o] [\FontAwesomeSymbol{f05d}]
+% \definesymbol [check-square] [\FontAwesomeSymbol{f14a}]
+% \definesymbol [check-square-o] [\FontAwesomeSymbol{f046}]
+% \definesymbol [chevron-circle-down] [\FontAwesomeSymbol{f13a}]
+% \definesymbol [chevron-circle-left] [\FontAwesomeSymbol{f137}]
+% \definesymbol [chevron-circle-right] [\FontAwesomeSymbol{f138}]
+% \definesymbol [chevron-circle-up] [\FontAwesomeSymbol{f139}]
+% \definesymbol [chevron-down] [\FontAwesomeSymbol{f078}]
+% \definesymbol [chevron-left] [\FontAwesomeSymbol{f053}]
+% \definesymbol [chevron-right] [\FontAwesomeSymbol{f054}]
+% \definesymbol [chevron-up] [\FontAwesomeSymbol{f077}]
+% \definesymbol [child] [\FontAwesomeSymbol{f1ae}]
+% \definesymbol [chrome] [\FontAwesomeSymbol{f268}]
+% \definesymbol [circle] [\FontAwesomeSymbol{f111}]
+% \definesymbol [circle-o] [\FontAwesomeSymbol{f10c}]
+% \definesymbol [circle-o-notch] [\FontAwesomeSymbol{f1ce}]
+% \definesymbol [circle-thin] [\FontAwesomeSymbol{f1db}]
+% \definesymbol [clipboard] [\FontAwesomeSymbol{f0ea}]
+% \definesymbol [clock-o] [\FontAwesomeSymbol{f017}]
+% \definesymbol [clone] [\FontAwesomeSymbol{f24d}]
+% \definesymbol [close] [\FontAwesomeSymbol{f00d}]
+% \definesymbol [cloud] [\FontAwesomeSymbol{f0c2}]
+% \definesymbol [cloud-download] [\FontAwesomeSymbol{f0ed}]
+% \definesymbol [cloud-upload] [\FontAwesomeSymbol{f0ee}]
+% \definesymbol [cny] [\FontAwesomeSymbol{f157}]
+% \definesymbol [code] [\FontAwesomeSymbol{f121}]
+% \definesymbol [code-fork] [\FontAwesomeSymbol{f126}]
+% \definesymbol [codepen] [\FontAwesomeSymbol{f1cb}]
+% \definesymbol [codiepie] [\FontAwesomeSymbol{f284}]
+% \definesymbol [coffee] [\FontAwesomeSymbol{f0f4}]
+% \definesymbol [cog] [\FontAwesomeSymbol{f013}]
+% \definesymbol [cogs] [\FontAwesomeSymbol{f085}]
+% \definesymbol [columns] [\FontAwesomeSymbol{f0db}]
+% \definesymbol [comment] [\FontAwesomeSymbol{f075}]
+% \definesymbol [comment-o] [\FontAwesomeSymbol{f0e5}]
+% \definesymbol [commenting] [\FontAwesomeSymbol{f27a}]
+% \definesymbol [commenting-o] [\FontAwesomeSymbol{f27b}]
+% \definesymbol [comments] [\FontAwesomeSymbol{f086}]
+% \definesymbol [comments-o] [\FontAwesomeSymbol{f0e6}]
+% \definesymbol [compass] [\FontAwesomeSymbol{f14e}]
+% \definesymbol [compress] [\FontAwesomeSymbol{f066}]
+% \definesymbol [connectdevelop] [\FontAwesomeSymbol{f20e}]
+% \definesymbol [contao] [\FontAwesomeSymbol{f26d}]
+% \definesymbol [copy] [\FontAwesomeSymbol{f0c5}]
+% \definesymbol [copyright] [\FontAwesomeSymbol{f1f9}]
+% \definesymbol [creative-commons] [\FontAwesomeSymbol{f25e}]
+% \definesymbol [credit-card] [\FontAwesomeSymbol{f09d}]
+% \definesymbol [credit-card-alt] [\FontAwesomeSymbol{f283}]
+% \definesymbol [crop] [\FontAwesomeSymbol{f125}]
+% \definesymbol [crosshairs] [\FontAwesomeSymbol{f05b}]
+% \definesymbol [css3] [\FontAwesomeSymbol{f13c}]
+% \definesymbol [cube] [\FontAwesomeSymbol{f1b2}]
+% \definesymbol [cubes] [\FontAwesomeSymbol{f1b3}]
+% \definesymbol [cut] [\FontAwesomeSymbol{f0c4}]
+% \definesymbol [cutlery] [\FontAwesomeSymbol{f0f5}]
+% \definesymbol [dashboard] [\FontAwesomeSymbol{f0e4}]
+% \definesymbol [dashcube] [\FontAwesomeSymbol{f210}]
+% \definesymbol [database] [\FontAwesomeSymbol{f1c0}]
+% \definesymbol [deaf] [\FontAwesomeSymbol{f2a4}]
+% \definesymbol [deafness] [\FontAwesomeSymbol{f2a4}]
+% \definesymbol [dedent] [\FontAwesomeSymbol{f03b}]
+% \definesymbol [delicious] [\FontAwesomeSymbol{f1a5}]
+% \definesymbol [desktop] [\FontAwesomeSymbol{f108}]
+% \definesymbol [deviantart] [\FontAwesomeSymbol{f1bd}]
+% \definesymbol [diamond] [\FontAwesomeSymbol{f219}]
+% \definesymbol [digg] [\FontAwesomeSymbol{f1a6}]
+% \definesymbol [dollar] [\FontAwesomeSymbol{f155}]
+% \definesymbol [dot-circle-o] [\FontAwesomeSymbol{f192}]
+% \definesymbol [download] [\FontAwesomeSymbol{f019}]
+% \definesymbol [dribbble] [\FontAwesomeSymbol{f17d}]
+% \definesymbol [dropbox] [\FontAwesomeSymbol{f16b}]
+% \definesymbol [drupal] [\FontAwesomeSymbol{f1a9}]
+% \definesymbol [edge] [\FontAwesomeSymbol{f282}]
+% \definesymbol [edit] [\FontAwesomeSymbol{f044}]
+% \definesymbol [eject] [\FontAwesomeSymbol{f052}]
+% \definesymbol [ellipsis-h] [\FontAwesomeSymbol{f141}]
+% \definesymbol [ellipsis-v] [\FontAwesomeSymbol{f142}]
+% \definesymbol [empire] [\FontAwesomeSymbol{f1d1}]
+% \definesymbol [envelope] [\FontAwesomeSymbol{f0e0}]
+% \definesymbol [envelope-o] [\FontAwesomeSymbol{f003}]
+% \definesymbol [envelope-square] [\FontAwesomeSymbol{f199}]
+% \definesymbol [envira] [\FontAwesomeSymbol{f299}]
+% \definesymbol [eraser] [\FontAwesomeSymbol{f12d}]
+% \definesymbol [eur] [\FontAwesomeSymbol{f153}]
+% \definesymbol [euro] [\FontAwesomeSymbol{f153}]
+% \definesymbol [exchange] [\FontAwesomeSymbol{f0ec}]
+% \definesymbol [exclamation] [\FontAwesomeSymbol{f12a}]
+% \definesymbol [exclamation-circle] [\FontAwesomeSymbol{f06a}]
+% \definesymbol [exclamation-triangle] [\FontAwesomeSymbol{f071}]
+% \definesymbol [expand] [\FontAwesomeSymbol{f065}]
+% \definesymbol [expeditedssl] [\FontAwesomeSymbol{f23e}]
+% \definesymbol [external-link] [\FontAwesomeSymbol{f08e}]
+% \definesymbol [external-link-square] [\FontAwesomeSymbol{f14c}]
+% \definesymbol [eye] [\FontAwesomeSymbol{f06e}]
+% \definesymbol [eye-slash] [\FontAwesomeSymbol{f070}]
+% \definesymbol [eyedropper] [\FontAwesomeSymbol{f1fb}]
+% \definesymbol [fa] [\FontAwesomeSymbol{f2b4}]
+% \definesymbol [facebook] [\FontAwesomeSymbol{f09a}]
+% \definesymbol [facebook-f] [\FontAwesomeSymbol{f09a}]
+% \definesymbol [facebook-official] [\FontAwesomeSymbol{f230}]
+% \definesymbol [facebook-square] [\FontAwesomeSymbol{f082}]
+% \definesymbol [fast-backward] [\FontAwesomeSymbol{f049}]
+% \definesymbol [fast-forward] [\FontAwesomeSymbol{f050}]
+% \definesymbol [fax] [\FontAwesomeSymbol{f1ac}]
+% \definesymbol [feed] [\FontAwesomeSymbol{f09e}]
+% \definesymbol [female] [\FontAwesomeSymbol{f182}]
+% \definesymbol [fighter-jet] [\FontAwesomeSymbol{f0fb}]
+% \definesymbol [file] [\FontAwesomeSymbol{f15b}]
+% \definesymbol [file-archive-o] [\FontAwesomeSymbol{f1c6}]
+% \definesymbol [file-audio-o] [\FontAwesomeSymbol{f1c7}]
+% \definesymbol [file-code-o] [\FontAwesomeSymbol{f1c9}]
+% \definesymbol [file-excel-o] [\FontAwesomeSymbol{f1c3}]
+% \definesymbol [file-image-o] [\FontAwesomeSymbol{f1c5}]
+% \definesymbol [file-movie-o] [\FontAwesomeSymbol{f1c8}]
+% \definesymbol [file-o] [\FontAwesomeSymbol{f016}]
+% \definesymbol [file-pdf-o] [\FontAwesomeSymbol{f1c1}]
+% \definesymbol [file-photo-o] [\FontAwesomeSymbol{f1c5}]
+% \definesymbol [file-picture-o] [\FontAwesomeSymbol{f1c5}]
+% \definesymbol [file-powerpoint-o] [\FontAwesomeSymbol{f1c4}]
+% \definesymbol [file-sound-o] [\FontAwesomeSymbol{f1c7}]
+% \definesymbol [file-text] [\FontAwesomeSymbol{f15c}]
+% \definesymbol [file-text-o] [\FontAwesomeSymbol{f0f6}]
+% \definesymbol [file-video-o] [\FontAwesomeSymbol{f1c8}]
+% \definesymbol [file-word-o] [\FontAwesomeSymbol{f1c2}]
+% \definesymbol [file-zip-o] [\FontAwesomeSymbol{f1c6}]
+% \definesymbol [files-o] [\FontAwesomeSymbol{f0c5}]
+% \definesymbol [film] [\FontAwesomeSymbol{f008}]
+% \definesymbol [filter] [\FontAwesomeSymbol{f0b0}]
+% \definesymbol [fire] [\FontAwesomeSymbol{f06d}]
+% \definesymbol [fire-extinguisher] [\FontAwesomeSymbol{f134}]
+% \definesymbol [firefox] [\FontAwesomeSymbol{f269}]
+% \definesymbol [first-order] [\FontAwesomeSymbol{f2b0}]
+% \definesymbol [flag] [\FontAwesomeSymbol{f024}]
+% \definesymbol [flag-checkered] [\FontAwesomeSymbol{f11e}]
+% \definesymbol [flag-o] [\FontAwesomeSymbol{f11d}]
+% \definesymbol [flash] [\FontAwesomeSymbol{f0e7}]
+% \definesymbol [flask] [\FontAwesomeSymbol{f0c3}]
+% \definesymbol [flickr] [\FontAwesomeSymbol{f16e}]
+% \definesymbol [floppy-o] [\FontAwesomeSymbol{f0c7}]
+% \definesymbol [folder] [\FontAwesomeSymbol{f07b}]
+% \definesymbol [folder-o] [\FontAwesomeSymbol{f114}]
+% \definesymbol [folder-open] [\FontAwesomeSymbol{f07c}]
+% \definesymbol [folder-open-o] [\FontAwesomeSymbol{f115}]
+% \definesymbol [font] [\FontAwesomeSymbol{f031}]
+% \definesymbol [font-awesome] [\FontAwesomeSymbol{f2b4}]
+% \definesymbol [fonticons] [\FontAwesomeSymbol{f280}]
+% \definesymbol [fort-awesome] [\FontAwesomeSymbol{f286}]
+% \definesymbol [forumbee] [\FontAwesomeSymbol{f211}]
+% \definesymbol [forward] [\FontAwesomeSymbol{f04e}]
+% \definesymbol [foursquare] [\FontAwesomeSymbol{f180}]
+% \definesymbol [frown-o] [\FontAwesomeSymbol{f119}]
+% \definesymbol [futbol-o] [\FontAwesomeSymbol{f1e3}]
+% \definesymbol [gamepad] [\FontAwesomeSymbol{f11b}]
+% \definesymbol [gavel] [\FontAwesomeSymbol{f0e3}]
+% \definesymbol [gbp] [\FontAwesomeSymbol{f154}]
+% \definesymbol [ge] [\FontAwesomeSymbol{f1d1}]
+% \definesymbol [gear] [\FontAwesomeSymbol{f013}]
+% \definesymbol [gears] [\FontAwesomeSymbol{f085}]
+% \definesymbol [genderless] [\FontAwesomeSymbol{f22d}]
+% \definesymbol [get-pocket] [\FontAwesomeSymbol{f265}]
+% \definesymbol [gg] [\FontAwesomeSymbol{f260}]
+% \definesymbol [gg-circle] [\FontAwesomeSymbol{f261}]
+% \definesymbol [gift] [\FontAwesomeSymbol{f06b}]
+% \definesymbol [git] [\FontAwesomeSymbol{f1d3}]
+% \definesymbol [git-square] [\FontAwesomeSymbol{f1d2}]
+% \definesymbol [github] [\FontAwesomeSymbol{f09b}]
+% \definesymbol [github-alt] [\FontAwesomeSymbol{f113}]
+% \definesymbol [github-square] [\FontAwesomeSymbol{f092}]
+% \definesymbol [gitlab] [\FontAwesomeSymbol{f296}]
+% \definesymbol [gittip] [\FontAwesomeSymbol{f184}]
+% \definesymbol [glass] [\FontAwesomeSymbol{f000}]
+% \definesymbol [glide] [\FontAwesomeSymbol{f2a5}]
+% \definesymbol [glide-g] [\FontAwesomeSymbol{f2a6}]
+% \definesymbol [globe] [\FontAwesomeSymbol{f0ac}]
+% \definesymbol [google] [\FontAwesomeSymbol{f1a0}]
+% \definesymbol [google-plus] [\FontAwesomeSymbol{f0d5}]
+% \definesymbol [google-plus-circle] [\FontAwesomeSymbol{f2b3}]
+% \definesymbol [google-plus-official] [\FontAwesomeSymbol{f2b3}]
+% \definesymbol [google-plus-square] [\FontAwesomeSymbol{f0d4}]
+% \definesymbol [google-wallet] [\FontAwesomeSymbol{f1ee}]
+% \definesymbol [graduation-cap] [\FontAwesomeSymbol{f19d}]
+% \definesymbol [gratipay] [\FontAwesomeSymbol{f184}]
+% \definesymbol [group] [\FontAwesomeSymbol{f0c0}]
+% \definesymbol [h-square] [\FontAwesomeSymbol{f0fd}]
+% \definesymbol [hacker-news] [\FontAwesomeSymbol{f1d4}]
+% \definesymbol [hand-grab-o] [\FontAwesomeSymbol{f255}]
+% \definesymbol [hand-lizard-o] [\FontAwesomeSymbol{f258}]
+% \definesymbol [hand-o-down] [\FontAwesomeSymbol{f0a7}]
+% \definesymbol [hand-o-left] [\FontAwesomeSymbol{f0a5}]
+% \definesymbol [hand-o-right] [\FontAwesomeSymbol{f0a4}]
+% \definesymbol [hand-o-up] [\FontAwesomeSymbol{f0a6}]
+% \definesymbol [hand-paper-o] [\FontAwesomeSymbol{f256}]
+% \definesymbol [hand-peace-o] [\FontAwesomeSymbol{f25b}]
+% \definesymbol [hand-pointer-o] [\FontAwesomeSymbol{f25a}]
+% \definesymbol [hand-rock-o] [\FontAwesomeSymbol{f255}]
+% \definesymbol [hand-scissors-o] [\FontAwesomeSymbol{f257}]
+% \definesymbol [hand-spock-o] [\FontAwesomeSymbol{f259}]
+% \definesymbol [hand-stop-o] [\FontAwesomeSymbol{f256}]
+% \definesymbol [hard-of-hearing] [\FontAwesomeSymbol{f2a4}]
+% \definesymbol [hashtag] [\FontAwesomeSymbol{f292}]
+% \definesymbol [hdd-o] [\FontAwesomeSymbol{f0a0}]
+% \definesymbol [header] [\FontAwesomeSymbol{f1dc}]
+% \definesymbol [headphones] [\FontAwesomeSymbol{f025}]
+% \definesymbol [heart] [\FontAwesomeSymbol{f004}]
+% \definesymbol [heart-o] [\FontAwesomeSymbol{f08a}]
+% \definesymbol [heartbeat] [\FontAwesomeSymbol{f21e}]
+% \definesymbol [history] [\FontAwesomeSymbol{f1da}]
+% \definesymbol [home] [\FontAwesomeSymbol{f015}]
+% \definesymbol [hospital-o] [\FontAwesomeSymbol{f0f8}]
+% \definesymbol [hotel] [\FontAwesomeSymbol{f236}]
+% \definesymbol [hourglass] [\FontAwesomeSymbol{f254}]
+% \definesymbol [hourglass-1] [\FontAwesomeSymbol{f251}]
+% \definesymbol [hourglass-2] [\FontAwesomeSymbol{f252}]
+% \definesymbol [hourglass-3] [\FontAwesomeSymbol{f253}]
+% \definesymbol [hourglass-end] [\FontAwesomeSymbol{f253}]
+% \definesymbol [hourglass-half] [\FontAwesomeSymbol{f252}]
+% \definesymbol [hourglass-o] [\FontAwesomeSymbol{f250}]
+% \definesymbol [hourglass-start] [\FontAwesomeSymbol{f251}]
+% \definesymbol [houzz] [\FontAwesomeSymbol{f27c}]
+% \definesymbol [html5] [\FontAwesomeSymbol{f13b}]
+% \definesymbol [i-cursor] [\FontAwesomeSymbol{f246}]
+% \definesymbol [ils] [\FontAwesomeSymbol{f20b}]
+% \definesymbol [image] [\FontAwesomeSymbol{f03e}]
+% \definesymbol [inbox] [\FontAwesomeSymbol{f01c}]
+% \definesymbol [indent] [\FontAwesomeSymbol{f03c}]
+% \definesymbol [industry] [\FontAwesomeSymbol{f275}]
+% \definesymbol [info] [\FontAwesomeSymbol{f129}]
+% \definesymbol [info-circle] [\FontAwesomeSymbol{f05a}]
+% \definesymbol [inr] [\FontAwesomeSymbol{f156}]
+% \definesymbol [instagram] [\FontAwesomeSymbol{f16d}]
+% \definesymbol [institution] [\FontAwesomeSymbol{f19c}]
+% \definesymbol [internet-explorer] [\FontAwesomeSymbol{f26b}]
+% \definesymbol [intersex] [\FontAwesomeSymbol{f224}]
+% \definesymbol [ioxhost] [\FontAwesomeSymbol{f208}]
+% \definesymbol [italic] [\FontAwesomeSymbol{f033}]
+% \definesymbol [joomla] [\FontAwesomeSymbol{f1aa}]
+% \definesymbol [jpy] [\FontAwesomeSymbol{f157}]
+% \definesymbol [jsfiddle] [\FontAwesomeSymbol{f1cc}]
+% \definesymbol [key] [\FontAwesomeSymbol{f084}]
+% \definesymbol [keyboard-o] [\FontAwesomeSymbol{f11c}]
+% \definesymbol [krw] [\FontAwesomeSymbol{f159}]
+% \definesymbol [language] [\FontAwesomeSymbol{f1ab}]
+% \definesymbol [laptop] [\FontAwesomeSymbol{f109}]
+% \definesymbol [lastfm] [\FontAwesomeSymbol{f202}]
+% \definesymbol [lastfm-square] [\FontAwesomeSymbol{f203}]
+% \definesymbol [leaf] [\FontAwesomeSymbol{f06c}]
+% \definesymbol [leanpub] [\FontAwesomeSymbol{f212}]
+% \definesymbol [legal] [\FontAwesomeSymbol{f0e3}]
+% \definesymbol [lemon-o] [\FontAwesomeSymbol{f094}]
+% \definesymbol [level-down] [\FontAwesomeSymbol{f149}]
+% \definesymbol [level-up] [\FontAwesomeSymbol{f148}]
+% \definesymbol [life-bouy] [\FontAwesomeSymbol{f1cd}]
+% \definesymbol [life-buoy] [\FontAwesomeSymbol{f1cd}]
+% \definesymbol [life-ring] [\FontAwesomeSymbol{f1cd}]
+% \definesymbol [life-saver] [\FontAwesomeSymbol{f1cd}]
+% \definesymbol [lightbulb-o] [\FontAwesomeSymbol{f0eb}]
+% \definesymbol [line-chart] [\FontAwesomeSymbol{f201}]
+% \definesymbol [link] [\FontAwesomeSymbol{f0c1}]
+% \definesymbol [linkedin] [\FontAwesomeSymbol{f0e1}]
+% \definesymbol [linkedin-square] [\FontAwesomeSymbol{f08c}]
+% \definesymbol [linux] [\FontAwesomeSymbol{f17c}]
+% \definesymbol [list] [\FontAwesomeSymbol{f03a}]
+% \definesymbol [list-alt] [\FontAwesomeSymbol{f022}]
+% \definesymbol [list-ol] [\FontAwesomeSymbol{f0cb}]
+% \definesymbol [list-ul] [\FontAwesomeSymbol{f0ca}]
+% \definesymbol [location-arrow] [\FontAwesomeSymbol{f124}]
+% \definesymbol [lock] [\FontAwesomeSymbol{f023}]
+% \definesymbol [long-arrow-down] [\FontAwesomeSymbol{f175}]
+% \definesymbol [long-arrow-left] [\FontAwesomeSymbol{f177}]
+% \definesymbol [long-arrow-right] [\FontAwesomeSymbol{f178}]
+% \definesymbol [long-arrow-up] [\FontAwesomeSymbol{f176}]
+% \definesymbol [low-vision] [\FontAwesomeSymbol{f2a8}]
+% \definesymbol [magic] [\FontAwesomeSymbol{f0d0}]
+% \definesymbol [magnet] [\FontAwesomeSymbol{f076}]
+% \definesymbol [mail-forward] [\FontAwesomeSymbol{f064}]
+% \definesymbol [mail-reply] [\FontAwesomeSymbol{f112}]
+% \definesymbol [mail-reply-all] [\FontAwesomeSymbol{f122}]
+% \definesymbol [male] [\FontAwesomeSymbol{f183}]
+% \definesymbol [map] [\FontAwesomeSymbol{f279}]
+% \definesymbol [map-marker] [\FontAwesomeSymbol{f041}]
+% \definesymbol [map-o] [\FontAwesomeSymbol{f278}]
+% \definesymbol [map-pin] [\FontAwesomeSymbol{f276}]
+% \definesymbol [map-signs] [\FontAwesomeSymbol{f277}]
+% \definesymbol [mars] [\FontAwesomeSymbol{f222}]
+% \definesymbol [mars-double] [\FontAwesomeSymbol{f227}]
+% \definesymbol [mars-stroke] [\FontAwesomeSymbol{f229}]
+% \definesymbol [mars-stroke-h] [\FontAwesomeSymbol{f22b}]
+% \definesymbol [mars-stroke-v] [\FontAwesomeSymbol{f22a}]
+% \definesymbol [maxcdn] [\FontAwesomeSymbol{f136}]
+% \definesymbol [meanpath] [\FontAwesomeSymbol{f20c}]
+% \definesymbol [medium] [\FontAwesomeSymbol{f23a}]
+% \definesymbol [medkit] [\FontAwesomeSymbol{f0fa}]
+% \definesymbol [meh-o] [\FontAwesomeSymbol{f11a}]
+% \definesymbol [mercury] [\FontAwesomeSymbol{f223}]
+% \definesymbol [microphone] [\FontAwesomeSymbol{f130}]
+% \definesymbol [microphone-slash] [\FontAwesomeSymbol{f131}]
+% \definesymbol [minus] [\FontAwesomeSymbol{f068}]
+% \definesymbol [minus-circle] [\FontAwesomeSymbol{f056}]
+% \definesymbol [minus-square] [\FontAwesomeSymbol{f146}]
+% \definesymbol [minus-square-o] [\FontAwesomeSymbol{f147}]
+% \definesymbol [mixcloud] [\FontAwesomeSymbol{f289}]
+% \definesymbol [mobile] [\FontAwesomeSymbol{f10b}]
+% \definesymbol [mobile-phone] [\FontAwesomeSymbol{f10b}]
+% \definesymbol [modx] [\FontAwesomeSymbol{f285}]
+% \definesymbol [money] [\FontAwesomeSymbol{f0d6}]
+% \definesymbol [moon-o] [\FontAwesomeSymbol{f186}]
+% \definesymbol [mortar-board] [\FontAwesomeSymbol{f19d}]
+% \definesymbol [motorcycle] [\FontAwesomeSymbol{f21c}]
+% \definesymbol [mouse-pointer] [\FontAwesomeSymbol{f245}]
+% \definesymbol [music] [\FontAwesomeSymbol{f001}]
+% \definesymbol [navicon] [\FontAwesomeSymbol{f0c9}]
+% \definesymbol [neuter] [\FontAwesomeSymbol{f22c}]
+% \definesymbol [newspaper-o] [\FontAwesomeSymbol{f1ea}]
+% \definesymbol [object-group] [\FontAwesomeSymbol{f247}]
+% \definesymbol [object-ungroup] [\FontAwesomeSymbol{f248}]
+% \definesymbol [odnoklassniki] [\FontAwesomeSymbol{f263}]
+% \definesymbol [odnoklassniki-square] [\FontAwesomeSymbol{f264}]
+% \definesymbol [opencart] [\FontAwesomeSymbol{f23d}]
+% \definesymbol [openid] [\FontAwesomeSymbol{f19b}]
+% \definesymbol [opera] [\FontAwesomeSymbol{f26a}]
+% \definesymbol [optin-monster] [\FontAwesomeSymbol{f23c}]
+% \definesymbol [outdent] [\FontAwesomeSymbol{f03b}]
+% \definesymbol [pagelines] [\FontAwesomeSymbol{f18c}]
+% \definesymbol [paint-brush] [\FontAwesomeSymbol{f1fc}]
+% \definesymbol [paper-plane] [\FontAwesomeSymbol{f1d8}]
+% \definesymbol [paper-plane-o] [\FontAwesomeSymbol{f1d9}]
+% \definesymbol [paperclip] [\FontAwesomeSymbol{f0c6}]
+% \definesymbol [paragraph] [\FontAwesomeSymbol{f1dd}]
+% \definesymbol [paste] [\FontAwesomeSymbol{f0ea}]
+% \definesymbol [pause] [\FontAwesomeSymbol{f04c}]
+% \definesymbol [pause-circle] [\FontAwesomeSymbol{f28b}]
+% \definesymbol [pause-circle-o] [\FontAwesomeSymbol{f28c}]
+% \definesymbol [paw] [\FontAwesomeSymbol{f1b0}]
+% \definesymbol [paypal] [\FontAwesomeSymbol{f1ed}]
+% \definesymbol [pencil] [\FontAwesomeSymbol{f040}]
+% \definesymbol [pencil-square] [\FontAwesomeSymbol{f14b}]
+% \definesymbol [pencil-square-o] [\FontAwesomeSymbol{f044}]
+% \definesymbol [percent] [\FontAwesomeSymbol{f295}]
+% \definesymbol [phone] [\FontAwesomeSymbol{f095}]
+% \definesymbol [phone-square] [\FontAwesomeSymbol{f098}]
+% \definesymbol [photo] [\FontAwesomeSymbol{f03e}]
+% \definesymbol [picture-o] [\FontAwesomeSymbol{f03e}]
+% \definesymbol [pie-chart] [\FontAwesomeSymbol{f200}]
+% \definesymbol [pied-piper] [\FontAwesomeSymbol{f2ae}]
+% \definesymbol [pied-piper-alt] [\FontAwesomeSymbol{f1a8}]
+% \definesymbol [pied-piper-pp] [\FontAwesomeSymbol{f1a7}]
+% \definesymbol [pinterest] [\FontAwesomeSymbol{f0d2}]
+% \definesymbol [pinterest-p] [\FontAwesomeSymbol{f231}]
+% \definesymbol [pinterest-square] [\FontAwesomeSymbol{f0d3}]
+% \definesymbol [plane] [\FontAwesomeSymbol{f072}]
+% \definesymbol [play] [\FontAwesomeSymbol{f04b}]
+% \definesymbol [play-circle] [\FontAwesomeSymbol{f144}]
+% \definesymbol [play-circle-o] [\FontAwesomeSymbol{f01d}]
+% \definesymbol [plug] [\FontAwesomeSymbol{f1e6}]
+% \definesymbol [plus] [\FontAwesomeSymbol{f067}]
+% \definesymbol [plus-circle] [\FontAwesomeSymbol{f055}]
+% \definesymbol [plus-square] [\FontAwesomeSymbol{f0fe}]
+% \definesymbol [plus-square-o] [\FontAwesomeSymbol{f196}]
+% \definesymbol [power-off] [\FontAwesomeSymbol{f011}]
+% \definesymbol [print] [\FontAwesomeSymbol{f02f}]
+% \definesymbol [product-hunt] [\FontAwesomeSymbol{f288}]
+% \definesymbol [puzzle-piece] [\FontAwesomeSymbol{f12e}]
+% \definesymbol [qq] [\FontAwesomeSymbol{f1d6}]
+% \definesymbol [qrcode] [\FontAwesomeSymbol{f029}]
+% \definesymbol [question] [\FontAwesomeSymbol{f128}]
+% \definesymbol [question-circle] [\FontAwesomeSymbol{f059}]
+% \definesymbol [question-circle-o] [\FontAwesomeSymbol{f29c}]
+% \definesymbol [quote-left] [\FontAwesomeSymbol{f10d}]
+% \definesymbol [quote-right] [\FontAwesomeSymbol{f10e}]
+% \definesymbol [ra] [\FontAwesomeSymbol{f1d0}]
+% \definesymbol [random] [\FontAwesomeSymbol{f074}]
+% \definesymbol [rebel] [\FontAwesomeSymbol{f1d0}]
+% \definesymbol [recycle] [\FontAwesomeSymbol{f1b8}]
+% \definesymbol [reddit] [\FontAwesomeSymbol{f1a1}]
+% \definesymbol [reddit-alien] [\FontAwesomeSymbol{f281}]
+% \definesymbol [reddit-square] [\FontAwesomeSymbol{f1a2}]
+% \definesymbol [refresh] [\FontAwesomeSymbol{f021}]
+% \definesymbol [registered] [\FontAwesomeSymbol{f25d}]
+% \definesymbol [remove] [\FontAwesomeSymbol{f00d}]
+% \definesymbol [renren] [\FontAwesomeSymbol{f18b}]
+% \definesymbol [reorder] [\FontAwesomeSymbol{f0c9}]
+% \definesymbol [repeat] [\FontAwesomeSymbol{f01e}]
+% \definesymbol [reply] [\FontAwesomeSymbol{f112}]
+% \definesymbol [reply-all] [\FontAwesomeSymbol{f122}]
+% \definesymbol [resistance] [\FontAwesomeSymbol{f1d0}]
+% \definesymbol [retweet] [\FontAwesomeSymbol{f079}]
+% \definesymbol [rmb] [\FontAwesomeSymbol{f157}]
+% \definesymbol [road] [\FontAwesomeSymbol{f018}]
+% \definesymbol [rocket] [\FontAwesomeSymbol{f135}]
+% \definesymbol [rotate-left] [\FontAwesomeSymbol{f0e2}]
+% \definesymbol [rotate-right] [\FontAwesomeSymbol{f01e}]
+% \definesymbol [rouble] [\FontAwesomeSymbol{f158}]
+% \definesymbol [rss] [\FontAwesomeSymbol{f09e}]
+% \definesymbol [rss-square] [\FontAwesomeSymbol{f143}]
+% \definesymbol [rub] [\FontAwesomeSymbol{f158}]
+% \definesymbol [ruble] [\FontAwesomeSymbol{f158}]
+% \definesymbol [rupee] [\FontAwesomeSymbol{f156}]
+% \definesymbol [safari] [\FontAwesomeSymbol{f267}]
+% \definesymbol [save] [\FontAwesomeSymbol{f0c7}]
+% \definesymbol [scissors] [\FontAwesomeSymbol{f0c4}]
+% \definesymbol [scribd] [\FontAwesomeSymbol{f28a}]
+% \definesymbol [search] [\FontAwesomeSymbol{f002}]
+% \definesymbol [search-minus] [\FontAwesomeSymbol{f010}]
+% \definesymbol [search-plus] [\FontAwesomeSymbol{f00e}]
+% \definesymbol [sellsy] [\FontAwesomeSymbol{f213}]
+% \definesymbol [send] [\FontAwesomeSymbol{f1d8}]
+% \definesymbol [send-o] [\FontAwesomeSymbol{f1d9}]
+% \definesymbol [server] [\FontAwesomeSymbol{f233}]
+% \definesymbol [share] [\FontAwesomeSymbol{f064}]
+% \definesymbol [share-alt] [\FontAwesomeSymbol{f1e0}]
+% \definesymbol [share-alt-square] [\FontAwesomeSymbol{f1e1}]
+% \definesymbol [share-square] [\FontAwesomeSymbol{f14d}]
+% \definesymbol [share-square-o] [\FontAwesomeSymbol{f045}]
+% \definesymbol [shekel] [\FontAwesomeSymbol{f20b}]
+% \definesymbol [sheqel] [\FontAwesomeSymbol{f20b}]
+% \definesymbol [shield] [\FontAwesomeSymbol{f132}]
+% \definesymbol [ship] [\FontAwesomeSymbol{f21a}]
+% \definesymbol [shirtsinbulk] [\FontAwesomeSymbol{f214}]
+% \definesymbol [shopping-bag] [\FontAwesomeSymbol{f290}]
+% \definesymbol [shopping-basket] [\FontAwesomeSymbol{f291}]
+% \definesymbol [shopping-cart] [\FontAwesomeSymbol{f07a}]
+% \definesymbol [sign-in] [\FontAwesomeSymbol{f090}]
+% \definesymbol [sign-language] [\FontAwesomeSymbol{f2a7}]
+% \definesymbol [sign-out] [\FontAwesomeSymbol{f08b}]
+% \definesymbol [signal] [\FontAwesomeSymbol{f012}]
+% \definesymbol [signing] [\FontAwesomeSymbol{f2a7}]
+% \definesymbol [simplybuilt] [\FontAwesomeSymbol{f215}]
+% \definesymbol [sitemap] [\FontAwesomeSymbol{f0e8}]
+% \definesymbol [skyatlas] [\FontAwesomeSymbol{f216}]
+% \definesymbol [skype] [\FontAwesomeSymbol{f17e}]
+% \definesymbol [slack] [\FontAwesomeSymbol{f198}]
+% \definesymbol [sliders] [\FontAwesomeSymbol{f1de}]
+% \definesymbol [slideshare] [\FontAwesomeSymbol{f1e7}]
+% \definesymbol [smile-o] [\FontAwesomeSymbol{f118}]
+% \definesymbol [snapchat] [\FontAwesomeSymbol{f2ab}]
+% \definesymbol [snapchat-ghost] [\FontAwesomeSymbol{f2ac}]
+% \definesymbol [snapchat-square] [\FontAwesomeSymbol{f2ad}]
+% \definesymbol [soccer-ball-o] [\FontAwesomeSymbol{f1e3}]
+% \definesymbol [sort] [\FontAwesomeSymbol{f0dc}]
+% \definesymbol [sort-alpha-asc] [\FontAwesomeSymbol{f15d}]
+% \definesymbol [sort-alpha-desc] [\FontAwesomeSymbol{f15e}]
+% \definesymbol [sort-amount-asc] [\FontAwesomeSymbol{f160}]
+% \definesymbol [sort-amount-desc] [\FontAwesomeSymbol{f161}]
+% \definesymbol [sort-asc] [\FontAwesomeSymbol{f0de}]
+% \definesymbol [sort-desc] [\FontAwesomeSymbol{f0dd}]
+% \definesymbol [sort-down] [\FontAwesomeSymbol{f0dd}]
+% \definesymbol [sort-numeric-asc] [\FontAwesomeSymbol{f162}]
+% \definesymbol [sort-numeric-desc] [\FontAwesomeSymbol{f163}]
+% \definesymbol [sort-up] [\FontAwesomeSymbol{f0de}]
+% \definesymbol [soundcloud] [\FontAwesomeSymbol{f1be}]
+% \definesymbol [space-shuttle] [\FontAwesomeSymbol{f197}]
+% \definesymbol [spinner] [\FontAwesomeSymbol{f110}]
+% \definesymbol [spoon] [\FontAwesomeSymbol{f1b1}]
+% \definesymbol [spotify] [\FontAwesomeSymbol{f1bc}]
+% \definesymbol [square] [\FontAwesomeSymbol{f0c8}]
+% \definesymbol [square-o] [\FontAwesomeSymbol{f096}]
+% \definesymbol [stack-exchange] [\FontAwesomeSymbol{f18d}]
+% \definesymbol [stack-overflow] [\FontAwesomeSymbol{f16c}]
+% \definesymbol [star] [\FontAwesomeSymbol{f005}]
+% \definesymbol [star-half] [\FontAwesomeSymbol{f089}]
+% \definesymbol [star-half-empty] [\FontAwesomeSymbol{f123}]
+% \definesymbol [star-half-full] [\FontAwesomeSymbol{f123}]
+% \definesymbol [star-half-o] [\FontAwesomeSymbol{f123}]
+% \definesymbol [star-o] [\FontAwesomeSymbol{f006}]
+% \definesymbol [steam] [\FontAwesomeSymbol{f1b6}]
+% \definesymbol [steam-square] [\FontAwesomeSymbol{f1b7}]
+% \definesymbol [step-backward] [\FontAwesomeSymbol{f048}]
+% \definesymbol [step-forward] [\FontAwesomeSymbol{f051}]
+% \definesymbol [stethoscope] [\FontAwesomeSymbol{f0f1}]
+% \definesymbol [sticky-note] [\FontAwesomeSymbol{f249}]
+% \definesymbol [sticky-note-o] [\FontAwesomeSymbol{f24a}]
+% \definesymbol [stop] [\FontAwesomeSymbol{f04d}]
+% \definesymbol [stop-circle] [\FontAwesomeSymbol{f28d}]
+% \definesymbol [stop-circle-o] [\FontAwesomeSymbol{f28e}]
+% \definesymbol [street-view] [\FontAwesomeSymbol{f21d}]
+% \definesymbol [strikethrough] [\FontAwesomeSymbol{f0cc}]
+% \definesymbol [stumbleupon] [\FontAwesomeSymbol{f1a4}]
+% \definesymbol [stumbleupon-circle] [\FontAwesomeSymbol{f1a3}]
+% \definesymbol [subscript] [\FontAwesomeSymbol{f12c}]
+% \definesymbol [subway] [\FontAwesomeSymbol{f239}]
+% \definesymbol [suitcase] [\FontAwesomeSymbol{f0f2}]
+% \definesymbol [sun-o] [\FontAwesomeSymbol{f185}]
+% \definesymbol [superscript] [\FontAwesomeSymbol{f12b}]
+% \definesymbol [support] [\FontAwesomeSymbol{f1cd}]
+% \definesymbol [table] [\FontAwesomeSymbol{f0ce}]
+% \definesymbol [tablet] [\FontAwesomeSymbol{f10a}]
+% \definesymbol [tachometer] [\FontAwesomeSymbol{f0e4}]
+% \definesymbol [tag] [\FontAwesomeSymbol{f02b}]
+% \definesymbol [tags] [\FontAwesomeSymbol{f02c}]
+% \definesymbol [tasks] [\FontAwesomeSymbol{f0ae}]
+% \definesymbol [taxi] [\FontAwesomeSymbol{f1ba}]
+% \definesymbol [television] [\FontAwesomeSymbol{f26c}]
+% \definesymbol [tencent-weibo] [\FontAwesomeSymbol{f1d5}]
+% \definesymbol [terminal] [\FontAwesomeSymbol{f120}]
+% \definesymbol [text-height] [\FontAwesomeSymbol{f034}]
+% \definesymbol [text-width] [\FontAwesomeSymbol{f035}]
+% \definesymbol [th] [\FontAwesomeSymbol{f00a}]
+% \definesymbol [th-large] [\FontAwesomeSymbol{f009}]
+% \definesymbol [th-list] [\FontAwesomeSymbol{f00b}]
+% \definesymbol [themeisle] [\FontAwesomeSymbol{f2b2}]
+% \definesymbol [thumb-tack] [\FontAwesomeSymbol{f08d}]
+% \definesymbol [thumbs-down] [\FontAwesomeSymbol{f165}]
+% \definesymbol [thumbs-o-down] [\FontAwesomeSymbol{f088}]
+% \definesymbol [thumbs-o-up] [\FontAwesomeSymbol{f087}]
+% \definesymbol [thumbs-up] [\FontAwesomeSymbol{f164}]
+% \definesymbol [ticket] [\FontAwesomeSymbol{f145}]
+% \definesymbol [times] [\FontAwesomeSymbol{f00d}]
+% \definesymbol [times-circle] [\FontAwesomeSymbol{f057}]
+% \definesymbol [times-circle-o] [\FontAwesomeSymbol{f05c}]
+% \definesymbol [tint] [\FontAwesomeSymbol{f043}]
+% \definesymbol [toggle-down] [\FontAwesomeSymbol{f150}]
+% \definesymbol [toggle-left] [\FontAwesomeSymbol{f191}]
+% \definesymbol [toggle-off] [\FontAwesomeSymbol{f204}]
+% \definesymbol [toggle-on] [\FontAwesomeSymbol{f205}]
+% \definesymbol [toggle-right] [\FontAwesomeSymbol{f152}]
+% \definesymbol [toggle-up] [\FontAwesomeSymbol{f151}]
+% \definesymbol [trademark] [\FontAwesomeSymbol{f25c}]
+% \definesymbol [train] [\FontAwesomeSymbol{f238}]
+% \definesymbol [transgender] [\FontAwesomeSymbol{f224}]
+% \definesymbol [transgender-alt] [\FontAwesomeSymbol{f225}]
+% \definesymbol [trash] [\FontAwesomeSymbol{f1f8}]
+% \definesymbol [trash-o] [\FontAwesomeSymbol{f014}]
+% \definesymbol [tree] [\FontAwesomeSymbol{f1bb}]
+% \definesymbol [trello] [\FontAwesomeSymbol{f181}]
+% \definesymbol [tripadvisor] [\FontAwesomeSymbol{f262}]
+% \definesymbol [trophy] [\FontAwesomeSymbol{f091}]
+% \definesymbol [truck] [\FontAwesomeSymbol{f0d1}]
+% \definesymbol [try] [\FontAwesomeSymbol{f195}]
+% \definesymbol [tty] [\FontAwesomeSymbol{f1e4}]
+% \definesymbol [tumblr] [\FontAwesomeSymbol{f173}]
+% \definesymbol [tumblr-square] [\FontAwesomeSymbol{f174}]
+% \definesymbol [turkish-lira] [\FontAwesomeSymbol{f195}]
+% \definesymbol [tv] [\FontAwesomeSymbol{f26c}]
+% \definesymbol [twitch] [\FontAwesomeSymbol{f1e8}]
+% \definesymbol [twitter] [\FontAwesomeSymbol{f099}]
+% \definesymbol [twitter-square] [\FontAwesomeSymbol{f081}]
+% \definesymbol [umbrella] [\FontAwesomeSymbol{f0e9}]
+% \definesymbol [underline] [\FontAwesomeSymbol{f0cd}]
+% \definesymbol [undo] [\FontAwesomeSymbol{f0e2}]
+% \definesymbol [universal-access] [\FontAwesomeSymbol{f29a}]
+% \definesymbol [university] [\FontAwesomeSymbol{f19c}]
+% \definesymbol [unlink] [\FontAwesomeSymbol{f127}]
+% \definesymbol [unlock] [\FontAwesomeSymbol{f09c}]
+% \definesymbol [unlock-alt] [\FontAwesomeSymbol{f13e}]
+% \definesymbol [unsorted] [\FontAwesomeSymbol{f0dc}]
+% \definesymbol [upload] [\FontAwesomeSymbol{f093}]
+% \definesymbol [usb] [\FontAwesomeSymbol{f287}]
+% \definesymbol [usd] [\FontAwesomeSymbol{f155}]
+% \definesymbol [user] [\FontAwesomeSymbol{f007}]
+% \definesymbol [user-md] [\FontAwesomeSymbol{f0f0}]
+% \definesymbol [user-plus] [\FontAwesomeSymbol{f234}]
+% \definesymbol [user-secret] [\FontAwesomeSymbol{f21b}]
+% \definesymbol [user-times] [\FontAwesomeSymbol{f235}]
+% \definesymbol [users] [\FontAwesomeSymbol{f0c0}]
+% \definesymbol [venus] [\FontAwesomeSymbol{f221}]
+% \definesymbol [venus-double] [\FontAwesomeSymbol{f226}]
+% \definesymbol [venus-mars] [\FontAwesomeSymbol{f228}]
+% \definesymbol [viacoin] [\FontAwesomeSymbol{f237}]
+% \definesymbol [viadeo] [\FontAwesomeSymbol{f2a9}]
+% \definesymbol [viadeo-square] [\FontAwesomeSymbol{f2aa}]
+% \definesymbol [video-camera] [\FontAwesomeSymbol{f03d}]
+% \definesymbol [vimeo] [\FontAwesomeSymbol{f27d}]
+% \definesymbol [vimeo-square] [\FontAwesomeSymbol{f194}]
+% \definesymbol [vine] [\FontAwesomeSymbol{f1ca}]
+% \definesymbol [vk] [\FontAwesomeSymbol{f189}]
+% \definesymbol [volume-control-phone] [\FontAwesomeSymbol{f2a0}]
+% \definesymbol [volume-down] [\FontAwesomeSymbol{f027}]
+% \definesymbol [volume-off] [\FontAwesomeSymbol{f026}]
+% \definesymbol [volume-up] [\FontAwesomeSymbol{f028}]
+% \definesymbol [warning] [\FontAwesomeSymbol{f071}]
+% \definesymbol [wechat] [\FontAwesomeSymbol{f1d7}]
+% \definesymbol [weibo] [\FontAwesomeSymbol{f18a}]
+% \definesymbol [weixin] [\FontAwesomeSymbol{f1d7}]
+% \definesymbol [whatsapp] [\FontAwesomeSymbol{f232}]
+% \definesymbol [wheelchair] [\FontAwesomeSymbol{f193}]
+% \definesymbol [wheelchair-alt] [\FontAwesomeSymbol{f29b}]
+% \definesymbol [wifi] [\FontAwesomeSymbol{f1eb}]
+% \definesymbol [wikipedia-w] [\FontAwesomeSymbol{f266}]
+% \definesymbol [windows] [\FontAwesomeSymbol{f17a}]
+% \definesymbol [won] [\FontAwesomeSymbol{f159}]
+% \definesymbol [wordpress] [\FontAwesomeSymbol{f19a}]
+% \definesymbol [wpbeginner] [\FontAwesomeSymbol{f297}]
+% \definesymbol [wpforms] [\FontAwesomeSymbol{f298}]
+% \definesymbol [wrench] [\FontAwesomeSymbol{f0ad}]
+% \definesymbol [xing] [\FontAwesomeSymbol{f168}]
+% \definesymbol [xing-square] [\FontAwesomeSymbol{f169}]
+% \definesymbol [y-combinator] [\FontAwesomeSymbol{f23b}]
+% \definesymbol [y-combinator-square] [\FontAwesomeSymbol{f1d4}]
+% \definesymbol [yahoo] [\FontAwesomeSymbol{f19e}]
+% \definesymbol [yc] [\FontAwesomeSymbol{f23b}]
+% \definesymbol [yc-square] [\FontAwesomeSymbol{f1d4}]
+% \definesymbol [yelp] [\FontAwesomeSymbol{f1e9}]
+% \definesymbol [yen] [\FontAwesomeSymbol{f157}]
+% \definesymbol [yoast] [\FontAwesomeSymbol{f2b1}]
+% \definesymbol [youtube] [\FontAwesomeSymbol{f167}]
+% \definesymbol [youtube-play] [\FontAwesomeSymbol{f16a}]
+% \definesymbol [youtube-square] [\FontAwesomeSymbol{f166}]
+
+\stopsymbolset
+
+\definefontsynonym [FontAwesomeBrands] [file:fontawesome5brandsregular400.otf]
+\definefontsynonym [FontAwesomeRegular] [file:fontawesome5freeregular400.otf]
+\definefontsynonym [FontAwesomeSolid] [file:fontawesome5freesolid900.otf]
+
+\startsymbolset [fontawesome-brands] [font=FontAwesomeBrands]
+ % Font Awesome Brands
+\stopsymbolset
+
+\startsymbolset [fontawesome-regular] [font=FontAwesomeRegular]
+ % Font Awesome Regular
+\stopsymbolset
+
+\startsymbolset [fontawesome-solid] [font=FontAwesomeSolid]
+ % Font Awesome Solid
\stopsymbolset
\continueifinputfile{symb-imp-fontawesome.mkiv}
-% \usesymbols[fontawesome]
+\usemodule[article-basic]
\starttext
- \showsymbolset[fontawesome]
+ % \usesymbols[fontawesome]
+ %
+ % \symbol[fontawesome][wheelchair]
+ % \symbol[fontawesome][angle-right]
+ % \symbol[fontawesome][angle right]
+ % \symbol[fontawesome][angle_right]
+
+ % \showsymbolset[fontawesome]
+
+ \startnamedsection [title] [title={Font Awesome Brands}]
+ \showsymbolset [fontawesome-brands]
+ \stopnamedsection
+
+ \startnamedsection [title] [title={Font Awesome Regular}]
+ \showsymbolset [fontawesome-regular]
+ \stopnamedsection
+
+ \startnamedsection [title] [title={Font Awesome Solid}]
+ \showsymbolset [fontawesome-solid]
+ \stopnamedsection
\stoptext
diff --git a/tex/context/base/mkiv/symb-imp-mis.mkiv b/tex/context/base/mkiv/symb-imp-mis.mkiv
index d2657512f..2320ea59a 100644
--- a/tex/context/base/mkiv/symb-imp-mis.mkiv
+++ b/tex/context/base/mkiv/symb-imp-mis.mkiv
@@ -21,34 +21,36 @@
\definesymbol [\v!none] []
-\definesymbol [bullet] [\textmath\bullet]
-\definesymbol [dash] [\textmath-]
-\definesymbol [star] [\textmath\star]
-\definesymbol [triangle] [\textmath\triangleright]
-\definesymbol [circle] [\textmath\circ]
-\definesymbol [square] [\textmath\square]
-\definesymbol [diamond] [\textmath\diamond]
+% \definesymbol [bullet] [\textmath\bullet]
+% \definesymbol [dash] [\textmath-]
+% \definesymbol [star] [\textmath\star]
+% \definesymbol [triangle] [\textmath\triangleright]
+% \definesymbol [circle] [\textmath\circ]
+% \definesymbol [square] [\textmath\square]
+% \definesymbol [diamond] [\textmath\diamond]
+% \definesymbol [asterisk] [\textmath\ast]
% I'm not sure about this ... I dislike the small bullet. So we provide
% it as variant: \type {\setupsymbolset[text]}. Also, we want to be
% backward compatible.
-\startsymbolset[text]
+% \startsymbolset[text]
\definesymbol [bullet] [\textormathchar{"2022}] % • \bullet
\definesymbol [dash] [\textormathchar{"2013}] % –
- \definesymbol [star] [\textormathchar{"22C6}] % ✴ \star
+ \definesymbol [star] [\textormathchar{"22C6}] % ⋆ \star
\definesymbol [triangle] [\textormathchar{"22B3}] % ⊳ \triangleright
\definesymbol [circle] [\textormathchar{"2218}] % ∘ \circ
\definesymbol [square] [\textormathchar{"25A1}] % □ \square
\definesymbol [diamond] [\textormathchar{"22C4}] % ⋄ \diamond
\definesymbol [checkmark] [\textormathchar{"2713}] % ✓ \checkmark
+ \definesymbol [asterisk] [\textormathchar{"2217}] % ∗ \asterisk
\definesymbol [blacktriangle] [\textormathchar{"25B6}] % ▶
\definesymbol [blacksquare] [\textormathchar{"25A0}] % ■
\definesymbol [blackdiamond] [\textormathchar{"25C6}] % ◆
-\stopsymbolset
+% \stopsymbolset
\definesymbol [smallcircle] [\hbox{\raise.1ex\hbox{\textmath{\scriptscriptstyle\bigcirc}}}]
\definesymbol [medcircle] [\hbox{\raise.1ex\hbox{\textmath{\scriptstyle \bigcirc}}}]
@@ -62,6 +64,7 @@
\definesymbol [6] [\symbol{medcircle}]
\definesymbol [7] [\symbol{bigcircle}]
\definesymbol [8] [\symbol{square}]
+\definesymbol [9] [\symbol{checkmark}]
\definesymbol [S] [\sectionmark]
\definesymbol [P] [\paragraphmark]
diff --git a/tex/context/base/mkiv/symb-imp-mvs.mkiv b/tex/context/base/mkiv/symb-imp-mvs.mkiv
index 9902fc9e8..f6a38214f 100644
--- a/tex/context/base/mkiv/symb-imp-mvs.mkiv
+++ b/tex/context/base/mkiv/symb-imp-mvs.mkiv
@@ -254,10 +254,16 @@
\stopsymbolset
-%D \showsymbolset[astronomic]
-%D \showsymbolset[zodiac]
-%D \showsymbolset[europe]
-%D \showsymbolset[martinvogel 1]
-%D \showsymbolset[martinvogel 2]
+\continueifinputfile{symb-imp-mvs.mkiv}
-\endinput
+\usemodule[article-basic]
+
+\starttext
+
+\startsubject[title={Astronomic}] \showsymbolset[astronomic] \stopsubject
+\startsubject[title={Zodiac}] \showsymbolset[zodiac] \stopsubject
+\startsubject[title={Europe}] \showsymbolset[europe] \stopsubject
+\startsubject[title={Martinvogel 1}] \showsymbolset[martinvogel 1] \stopsubject
+\startsubject[title={Martinvogel 2}] \showsymbolset[martinvogel 2] \stopsubject
+
+\stoptext
diff --git a/tex/context/base/mkiv/symb-ini.mkiv b/tex/context/base/mkiv/symb-ini.mkiv
index e4950e09d..abf857675 100644
--- a/tex/context/base/mkiv/symb-ini.mkiv
+++ b/tex/context/base/mkiv/symb-ini.mkiv
@@ -45,6 +45,7 @@
\installcorenamespace{symbol}
\installcorenamespace{symbolset}
+\installcorenamespace{symboldefault}
\let\currentsymbol \empty
\let\currentsymbolset\empty
@@ -95,8 +96,9 @@
% Test test \symbol[whatever]\ test \symbol[whatever].
% Test test \symbol{whatever} test \symbol{whatever}.
-\unexpanded\def\symbol % This one always gobbles spaces,
- {\dodoubleempty\symb_place} % so never change it again!
+\unexpanded\def\symbol
+ {\dontleavehmode % so we can start a paragraph with it
+ \dodoubleempty\symb_place}
\def\symb_place % so we also handle \symbol{name}
{\iffirstargument % which is nicer with following spaces
@@ -112,13 +114,23 @@
\expandafter\symb_place_normal_b
\fi}
+% \def\symb_place_normal_a[#1][#2]%
+% {\edef\currentsymbol{#2}%
+% \ifcsname\??symbol#1:#2\endcsname
+% \symb_place_indeed{#1:#2}%
+% \else
+% \symb_place_normal_c
+% \fi}
+
\def\symb_place_normal_a[#1][#2]%
{\edef\currentsymbol{#2}%
\ifcsname\??symbol#1:#2\endcsname
- \symb_place_indeed{#1:#2}%
+ \symb_place_indeed{#1:#2}% maybe use \lastnamescs
+ \else\ifcsname\??symboldefault#1\endcsname
+ \symb_place_named{#1}% maybe use \lastnamescs
\else
\symb_place_normal_c
- \fi}
+ \fi\fi}
\def\symb_place_normal_b[#1][#2]%
{\edef\currentsymbol{#1}%
@@ -160,11 +172,47 @@
\expandafter\symb_fetch_indeed
\fi}
+% \def\symb_fetch_indeed#1%
+% {\ifcsname\??symbol#1:\currentsymbol\endcsname
+% \symb_place_indeed{#1:\currentsymbol}%
+% \fi}
+
\def\symb_fetch_indeed#1%
{\ifcsname\??symbol#1:\currentsymbol\endcsname
\symb_place_indeed{#1:\currentsymbol}%
+ \else\ifcsname\??symboldefault#1\endcsname
+ \symb_place_named{#1}%
+ \fi\fi}
+
+\def\symb_place_named#1% \relax's prevent lookahead problems
+ {\begingroup
+ \setbox\scratchbox\hbox\bgroup
+ \the\everysymbol
+ \getglyphstyled
+ {\csname\??symboldefault#1\endcsname}%
+ {\tochar{n:\currentsymbol}}%
+ \relax
+ \egroup
+ \ifdim\wd\scratchbox>\zeropoint
+ \unhbox\scratchbox
+ \endgroup
+ \setxvalue{\??symbol#1:\currentsymbol}%
+ {\symb_place_named_indeed{#1}{\currentsymbol}}%
+ \settrue\c_symb_found
+ \else
+ \endgroup
\fi}
+\unexpanded\def\symb_place_named_indeed#1#2% \relax's prevent lookahead problems
+ {\settrue\c_symb_found
+ \begingroup
+ \the\everysymbol
+ \getglyphstyled
+ {\csname\??symboldefault#1\endcsname}%
+ {\tochar{n:#2}}%
+ \relax
+ \endgroup}
+
\def\symb_place_retry#1%
{\ifcsname\??symbol:#1\endcsname
\symb_place_indeed{:#1}%
@@ -273,9 +321,25 @@
\installcorenamespace{symbolsets}
-\unexpanded\def\startsymbolset[#1]%
+% \unexpanded\def\startsymbolset[#1]%
+% {\pushmacro\m_symb_current_set
+% \def\m_symb_current_set{#1}}
+
+% maybe a parameterhandler:
+
+\unexpanded\def\startsymbolset
+ {\dodoubleargument\symb_start_set}
+
+\def\symb_start_set[#1][#2]%
{\pushmacro\m_symb_current_set
- \def\m_symb_current_set{#1}}
+ \def\m_symb_current_set{#1}%
+ \ifsecondargument
+ \getdummyparameters[\s!font=,#2]%
+ \edef\p_font{\dummyparameter\s!font}%
+ \ifx\p_font\empty\else
+ \letvalue{\??symboldefault#1}\p_font
+ \fi
+ \fi}
\unexpanded\def\stopsymbolset
{\popmacro\m_symb_current_set}
diff --git a/tex/context/base/mkiv/symb-run.mkiv b/tex/context/base/mkiv/symb-run.mkiv
index ed4d90861..c25d13d48 100644
--- a/tex/context/base/mkiv/symb-run.mkiv
+++ b/tex/context/base/mkiv/symb-run.mkiv
@@ -12,23 +12,55 @@
%C details.
\startluacode
- function commands.showsymbolset(collection,symbols)
+ function commands.showsymbolset(collection,symbols,fontid)
if type(symbols) == "string" then
symbols = utilities.parsers.settings_to_array(symbols)
end
+ local options = { framecolor = "orange", rulethickness = ".8pt", offset = interfaces.variables.overlay }
+ local list = table.tohash(symbols)
+ local alsofont = fontid > 0
+ local defined = #symbols > 0
+ local byname = false
+ if alsofont then
+ local is_symbol = characters.is_symbol
+ local chardata = characters.data
+ local resources = fonts.hashes.resources [fontid]
+ local characters = fonts.hashes.characters[fontid]
+ if resources and characters then
+ local unicodes = resources.unicodes
+ if unicodes then
+ for name, unicode in next, unicodes do
+ if not list[name] and name ~= ".notdef" then
+ local c = rawget(chardata,unicode)
+ if not c or is_symbol[c.category] then
+ list[name] = false
+ byname = true
+ end
+ end
+ end
+ end
+ end
+ end
+ local detail = defined and byname
context.start()
context.forcesymbolset { collection }
- context.starttabulate { "|lT|l|l|" }
- local options = { framecolor = "orange", rulethickness = ".8pt", offset = interfaces.variables.overlay }
- for i=1,#symbols do
- local symbol = symbols[i]
+ context.starttabulate { detail and "|lT|l|l|lT|" or "|lT|l|l|"}
+ for symbol, how in table.sortedhash(list) do
context.NC()
- context(symbol)
+ if detail and how then
+ context.bold(symbol)
+ else
+ context(symbol)
+ end
context.NC()
context.symbol(symbol)
context.NC()
context.framed(options,context.nested.symbol(symbol))
context.NC()
+ if detail and how then
+ context.bold("defined")
+ context.NC()
+ end
context.NR()
end
context.stoptabulate()
@@ -42,7 +74,23 @@
{\dosingleargument\symb_show_set}
\gdef\symb_show_set[#1]%
- {\ctxcommand{showsymbolset("#1","\symbolset{#1}")}}
+ {\begingroup
+ \edef\p_font{\begincsname\??symboldefault#1\endcsname}%
+ \begingroup
+ \ifx\p_font\empty
+ \global\globalscratchcounter\zerocount
+ \else
+ \definedfont[\p_font]%
+ \global\globalscratchcounter\fontid\font\relax
+ \fi
+ \endgroup
+ \ctxcommand {
+ showsymbolset (
+ "#1",
+ "\symbolset{#1}",
+ \the\globalscratchcounter
+ ) }%
+ \endgroup}
\protect
diff --git a/tex/context/base/mkiv/syst-aux.lua b/tex/context/base/mkiv/syst-aux.lua
index f9d8505f1..9b0ca82c4 100644
--- a/tex/context/base/mkiv/syst-aux.lua
+++ b/tex/context/base/mkiv/syst-aux.lua
@@ -323,9 +323,47 @@ end
implement { name = "texdefinition_one", actions = texdefinition_one, scope = "private", arguments = "string" }
implement { name = "texdefinition_two", actions = texdefinition_two, scope = "private" }
-implement { name = "upper", arguments = "string", actions = { utf.upper, context } }
-implement { name = "lower", arguments = "string", actions = { utf.lower, context } }
-implement { name = "strip", arguments = "string", actions = { string.strip, context } } -- or utf.strip
+do
+
+ -- Quite probably we don't yet have characters loaded so we delay some
+ -- aliases.
+
+ local _lower_, _upper_, _strip_
+
+ _lower_ = function(s)
+ if characters and characters.lower then
+ _lower_ = characters.lower
+ return _lower_(s)
+ end
+ return string.lower(s)
+ end
+
+ _upper_ = function(s)
+ if characters and characters.upper then
+ _upper_ = characters.upper
+ return _upper_(s)
+ end
+ return string.upper(s)
+ end
+
+ _strip_ = function(s)
+ -- or utf.strip
+ if string.strip then
+ _strip_ = string.strip
+ return _strip_(s)
+ end
+ return s
+ end
+
+ local function lower(s) context(_lower_(s)) end
+ local function upper(s) context(_upper_(s)) end
+ local function strip(s) context(_strip_(s)) end
+
+ implement { name = "upper", arguments = "string", actions = upper }
+ implement { name = "lower", arguments = "string", actions = lower }
+ implement { name = "strip", arguments = "string", actions = strip }
+
+end
implement {
name = "converteddimen",
@@ -373,10 +411,17 @@ implement {
-- not faster but just less tracing:
-local firstoftwoarguments = context.firstoftwoarguments
-local secondoftwoarguments = context.secondoftwoarguments
-local firstofoneargument = context.firstofoneargument
-local gobbleoneargument = context.gobbleoneargument
+local ctx_protected_cs = context.protected.cs -- more efficient
+
+local ctx_firstoftwoarguments = ctx_protected_cs.firstoftwoarguments
+local ctx_secondoftwoarguments = ctx_protected_cs.secondoftwoarguments
+local ctx_firstofoneargument = ctx_protected_cs.firstofoneargument
+local ctx_gobbleoneargument = ctx_protected_cs.gobbleoneargument
+
+context.firstoftwoarguments = ctx_firstoftwoarguments
+context.secondoftwoarguments = ctx_secondoftwoarguments
+context.firstofoneargument = ctx_firstofoneargument
+context.gobbleoneargument = ctx_gobbleoneargument
local hash = utilities.parsers.hashes.settings_to_set
@@ -384,9 +429,9 @@ local function doifelsecommon(a,b)
if a == b then
setmacro("commalistelement",a)
if a == "" then
- secondoftwoarguments()
+ ctx_secondoftwoarguments()
else
- firstoftwoarguments()
+ ctx_firstoftwoarguments()
end
return
end
@@ -400,7 +445,7 @@ local function doifelsecommon(a,b)
for k in next, ha do
if hb[k] then
setmacro("commalistelement",k)
- firstoftwoarguments()
+ ctx_firstoftwoarguments()
return
end
end
@@ -408,28 +453,28 @@ local function doifelsecommon(a,b)
if hash[a][b] then
-- if settings_to_set(a)[b] then
setmacro("commalistelement",b)
- firstoftwoarguments()
+ ctx_firstoftwoarguments()
return
end
elseif bb then
if hash[b][a] then
-- if settings_to_set(b)[a] then
setmacro("commalistelement",a)
- firstoftwoarguments()
+ ctx_firstoftwoarguments()
return
end
end
setmacro("commalistelement","")
- secondoftwoarguments()
+ ctx_secondoftwoarguments()
end
local function doifcommon(a,b)
if a == b then
setmacro("commalistelement",a)
if a == "" then
- gobbleoneargument()
+ ctx_gobbleoneargument()
else
- firstofoneargument()
+ ctx_firstofoneargument()
end
return
end
@@ -443,7 +488,7 @@ local function doifcommon(a,b)
for k in next, ha do
if hb[k] then
setmacro("commalistelement",k)
- firstofoneargument()
+ ctx_firstofoneargument()
return
end
end
@@ -451,28 +496,28 @@ local function doifcommon(a,b)
if hash[a][b] then
-- if settings_to_set(a)[b] then
setmacro("commalistelement",b)
- firstofoneargument()
+ ctx_firstofoneargument()
return
end
elseif bb then
if hash[b][a] then
-- if settings_to_set(b)[a] then
setmacro("commalistelement",a)
- firstofoneargument()
+ ctx_firstofoneargument()
return
end
end
setmacro("commalistelement","")
- gobbleoneargument()
+ ctx_gobbleoneargument()
end
local function doifnotcommon(a,b)
if a == b then
setmacro("commalistelement",a)
if a == "" then
- firstofoneargument()
+ ctx_firstofoneargument()
else
- gobbleoneargument()
+ ctx_gobbleoneargument()
end
return
end
@@ -486,7 +531,7 @@ local function doifnotcommon(a,b)
for k in next, ha do
if hb[k] then
setmacro("commalistelement",k)
- gobbleoneargument()
+ ctx_gobbleoneargument()
return
end
end
@@ -494,28 +539,28 @@ local function doifnotcommon(a,b)
if hash[a][b] then
-- if settings_to_set(a)[b] then
setmacro("commalistelement",b)
- gobbleoneargument()
+ ctx_gobbleoneargument()
return
end
elseif bb then
if hash[b][a] then
-- if settings_to_set(b)[a] then
setmacro("commalistelement",a)
- gobbleoneargument()
+ ctx_gobbleoneargument()
return
end
end
setmacro("commalistelement","")
- firstofoneargument()
+ ctx_firstofoneargument()
end
local function doifelseinset(a,b)
if a == b then
setmacro("commalistelement",a)
if a == "" then
- secondoftwoarguments()
+ ctx_secondoftwoarguments()
else
- firstoftwoarguments()
+ ctx_firstoftwoarguments()
end
return
end
@@ -524,21 +569,21 @@ local function doifelseinset(a,b)
if hash[b][a] then
-- if settings_to_set(b)[a] then
setmacro("commalistelement",a)
- firstoftwoarguments()
+ ctx_firstoftwoarguments()
return
end
end
setmacro("commalistelement","")
- secondoftwoarguments()
+ ctx_secondoftwoarguments()
end
local function doifinset(a,b)
if a == b then
setmacro("commalistelement",a)
if a == "" then
- gobbleoneargument()
+ ctx_gobbleoneargument()
else
- firstofoneargument()
+ ctx_firstofoneargument()
end
return
end
@@ -547,21 +592,21 @@ local function doifinset(a,b)
if hash[b][a] then
-- if settings_to_set(b)[a] then
setmacro("commalistelement",a)
- firstofoneargument()
+ ctx_firstofoneargument()
return
end
end
setmacro("commalistelement","")
- gobbleoneargument()
+ ctx_gobbleoneargument()
end
local function doifnotinset(a,b)
if a == b then
setmacro("commalistelement",a)
if a == "" then
- firstofoneargument()
+ ctx_firstofoneargument()
else
- gobbleoneargument()
+ ctx_gobbleoneargument()
end
return
end
@@ -570,12 +615,12 @@ local function doifnotinset(a,b)
if hash[b][a] then
-- if settings_to_set(b)[a] then
setmacro("commalistelement",a)
- gobbleoneargument()
+ ctx_gobbleoneargument()
return
end
end
setmacro("commalistelement","")
- firstofoneargument()
+ ctx_firstofoneargument()
end
implement {
@@ -614,6 +659,20 @@ implement {
arguments = "2 strings",
}
+-- done elsewhere:
+--
+-- local function firstinset(a)
+-- local aa = hash[a]
+-- context(aa and aa[1] or a)
+-- end
+--
+-- implement {
+-- name = "firstinset",
+-- actions = firstinset,
+-- arguments = "string",
+-- private = false,
+-- }
+
-- implement {
-- name = "stringcompare",
-- arguments = "2 strings",
diff --git a/tex/context/base/mkiv/syst-aux.mkiv b/tex/context/base/mkiv/syst-aux.mkiv
index 77f947753..3004c08b8 100644
--- a/tex/context/base/mkiv/syst-aux.mkiv
+++ b/tex/context/base/mkiv/syst-aux.mkiv
@@ -181,12 +181,9 @@
%D These are not needed any more now that we have wide screens (and bytes come
%D cheap).
-\let\@EA \singleexpandafter
-\let\@EAEAEA \doubleexpandafter
-\let\@EAEAEAEAEAEA\tripleexpandafter
-
-\let\@NX \noexpand
-\def\@EAEA {\expandafter\expandafter} % can often be avoided
+\let\@EA \singleexpandafter % obsolete
+\let\@EAEAEA \doubleexpandafter % obsolete
+\let\@EAEAEAEAEAEA\tripleexpandafter % obsolete
%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},
@@ -345,6 +342,18 @@
\let\doifnextoptionalelse \doifelsenextoptional
\let\doifnextoptionalcselse\doifelsenextoptionalcs
+% fails on assignments
+%
+% \unexpanded\def\doifelsenextoptional {\afterassignment\doifelsenextoptional_n \def\m_syst_action_yes}
+% \def\doifelsenextoptional_n {\afterassignment\doifelsenextoptional_n_n\def\m_syst_action_nop}
+% \def\doifelsenextoptional_n_n {\let\if_next_blank_space_token\iffalse
+% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+%
+% \unexpanded\def\doifelsenextoptionalcs {\afterassignment\doifelsenextoptionalcs_n \let\m_syst_action_yes}
+% \def\doifelsenextoptionalcs_n {\afterassignment\doifelsenextoptionalcs_n_n\let\m_syst_action_nop}
+% \def\doifelsenextoptionalcs_n_n{\let\if_next_blank_space_token\iffalse
+% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
\def\syst_helpers_inspect_next_optional_character
{\ifx\nexttoken\blankspace
\expandafter\syst_helpers_reinspect_next_optional_character
@@ -491,8 +500,6 @@
%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} {...}
-
\let\next\:
\def\:{\let\blankspace= } \:
@@ -514,6 +521,31 @@
\let\:\next
+%D This is much nicer and works too:
+
+% \def\firstofoneargument#1{#1}
+%
+% \expandafter\let\firstofoneargument{\blankspace= }
+%
+% \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_character
+% } {\let\if_next_blank_space_token\iftrue
+% \futurelet\nexttoken\syst_helpers_inspect_next_character}
+%
+% \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_optional_character
+% } {\let\if_next_blank_space_token\iftrue
+% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+%
+% \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_bgroup_character
+% } {\let\if_next_blank_space_token\iftrue
+% \futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
+%
+% \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_parenthesis_character
+% } {\let\if_next_blank_space_token\iftrue
+% \futurelet\nexttoken\syst_helpers_inspect_next_parenthesis_character}
+%
+% \expandafter\def\firstofoneargument{\syst_helpers_ignore_spacing_blankspace
+% } {\futurelet\nexttoken\syst_helpers_ignore_spacing}
+
%D \macros
%D {setvalue,setgvalue,setevalue,setxvalue,
%D letvalue,letgvalue,getvalue,resetvalue,
@@ -529,7 +561,7 @@
%D \setevalue {name}{...} = \edef\name{...}
%D \setxvalue {name}{...} = \xdef\name{...}
%D \letvalue {name}=\... = \let\name=\...
-%D \letgvalue {name}=\... = \global\let\name=\...
+%D \letgvalue {name}=\... = \glet\name=\...
%D \getvalue {name} = \name
%D \resetvalue {name} = \def\name{}
%D \stoptyping
@@ -537,16 +569,16 @@
%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\setvalue #1{\expandafter\def \csname#1\endcsname}
\def\setgvalue #1{\expandafter\gdef\csname#1\endcsname}
\def\setevalue #1{\expandafter\edef\csname#1\endcsname}
\def\setxvalue #1{\expandafter\xdef\csname#1\endcsname}
-\def\getvalue #1{\csname#1\endcsname}
-\def\letvalue #1{\expandafter\let\csname#1\endcsname}
-\def\letgvalue #1{\global\expandafter\let\csname#1\endcsname}
-\def\resetvalue #1{\expandafter\let\csname#1\endcsname\empty}
-\def\undefinevalue#1{\expandafter\let\csname#1\endcsname\undefined}
-\def\ignorevalue#1#2{\expandafter\let\csname#1\endcsname\empty}
+\def\getvalue #1{\csname#1\endcsname} % maybe: \begincsname#1\endcsname
+\def\letvalue #1{\expandafter\let \csname#1\endcsname}
+\def\letgvalue #1{\expandafter\glet\csname#1\endcsname}
+\def\resetvalue #1{\expandafter\let \csname#1\endcsname\empty}
+\def\undefinevalue#1{\expandafter\let \csname#1\endcsname\undefined}
+\def\ignorevalue#1#2{\expandafter\let \csname#1\endcsname\empty}
\def\setuvalue #1{\normalprotected\expandafter \def\csname#1\endcsname}
\def\setuevalue #1{\normalprotected\expandafter\edef\csname#1\endcsname}
@@ -562,7 +594,7 @@
%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:
-\unexpanded\def\glet{\global\let} \let\globallet\glet
+\let\globallet\glet
%D \macros
%D {doifundefined,doifdefined,
@@ -635,7 +667,7 @@
{\ifcsname#1\endcsname\expandafter\let\csname#1\endcsname\undefined\fi}
\def\globalundefine#1% conditional
- {\ifcsname#1\endcsname\expandafter\global\let\csname#1\endcsname\undefined\fi}
+ {\ifcsname#1\endcsname\expandafter\glet\csname#1\endcsname\undefined\fi}
%D Beware, being \type {\undefined} in \ETEX\ means that the macro {\em is} defined!
%D
@@ -705,6 +737,23 @@
\expandafter\secondoftwoarguments
\fi}
+%D Slightly faster on longer arguments (0.179 downto 0.141):
+%D
+%D \testfeatureonce{100000}{\doifelse{aaaaaaaaaaaaaaa}{bbbbbbbbbbbbbbb}\relax\relax}
+
+% \unexpanded\def\doifelse
+% {\afterassignment\doifelse_n\edef\m_syst_string_one}
+%
+% \unexpanded\def\doifelse_n
+% {\afterassignment\doifelse_n_n\edef\m_syst_string_two}
+%
+% \unexpanded\def\doifelse_n_n
+% {\ifx\m_syst_string_one\m_syst_string_two
+% \expandafter\firstoftwoarguments
+% \else
+% \expandafter\secondoftwoarguments
+% \fi}
+
%D \macros
%D {doifempty,doifemptyelse,doifnotempty}
%D
@@ -912,6 +961,7 @@
\unexpanded\def\doifelseinset#1#2{\clf_doifelseinset{#1}{#2}}
\unexpanded\def\doifinset #1#2{\clf_doifinset {#1}{#2}}
\unexpanded\def\doifnotinset #1#2{\clf_doifnotinset {#1}{#2}}
+ % \let\firstinset \clf_firstinset
\let\doifinsetelse\doifelseinset
@@ -1348,7 +1398,7 @@
%D
%D Sometimes the action to be undertaken depends on the
%D next character. This macro get this character and puts it in
-%D \type{\firstcharacter}.
+%D \type {\firstcharacter}.
%D
%D \starttyping
%D \getfirstcharacter {string}
@@ -2243,202 +2293,517 @@
% \dotripleempty\test[] xxx\par
% \dotripleempty\test xxx\par
+%D Common:
+
+\newtoks\t_syst_aux
+
+% \def\syst_helpers_empty_spaced_six {\expandafter\m_syst_aux_do\the\t_syst_aux[][][][][][] }
+% \def\syst_helpers_empty_normal_six {\expandafter\m_syst_aux_do\the\t_syst_aux[][][][][][]}
+% \def\syst_helpers_empty_spaced_five {\expandafter\m_syst_aux_do\the\t_syst_aux[][][][][] }
+% \def\syst_helpers_empty_normal_five {\expandafter\m_syst_aux_do\the\t_syst_aux[][][][][]}
+% \def\syst_helpers_empty_spaced_four {\expandafter\m_syst_aux_do\the\t_syst_aux[][][][] }
+% \def\syst_helpers_empty_normal_four {\expandafter\m_syst_aux_do\the\t_syst_aux[][][][]}
+% \def\syst_helpers_empty_spaced_three{\expandafter\m_syst_aux_do\the\t_syst_aux[][][] }
+% \def\syst_helpers_empty_normal_three{\expandafter\m_syst_aux_do\the\t_syst_aux[][][]}
+% \def\syst_helpers_empty_spaced_two {\expandafter\m_syst_aux_do\the\t_syst_aux[][] }
+% \def\syst_helpers_empty_normal_two {\expandafter\m_syst_aux_do\the\t_syst_aux[][]}
+% \def\syst_helpers_empty_spaced_one {\expandafter\m_syst_aux_do\the\t_syst_aux[] }
+% \def\syst_helpers_empty_normal_one {\expandafter\m_syst_aux_do\the\t_syst_aux[]}
+%
+% \def\syst_helpers_single_empty_one_yes {\firstargumenttrue \m_syst_aux_do}
+% \def\syst_helpers_double_empty_two_yes {\secondargumenttrue \expandafter\m_syst_aux_do\the\t_syst_aux}
+% \def\syst_helpers_triple_empty_three_yes {\thirdargumenttrue \expandafter\m_syst_aux_do\the\t_syst_aux}
+% \def\syst_helpers_quadruple_empty_four_yes {\fourthargumenttrue \expandafter\m_syst_aux_do\the\t_syst_aux}
+% \def\syst_helpers_quintuple_empty_five_yes {\fifthargumenttrue \expandafter\m_syst_aux_do\the\t_syst_aux}
+% \def\syst_helpers_sixtuple_empty_six_yes {\sixthargumenttrue \expandafter\m_syst_aux_do\the\t_syst_aux}
+% \def\syst_helpers_seventuple_empty_seven_yes{\seventhargumenttrue\expandafter\m_syst_aux_do\the\t_syst_aux}
+%
+% with
+%
+% \unexpanded\def\dodoubleempty#1%
+% {\syst_helpers_argument_reset
+% \let\m_syst_aux_do#1% alias
+% \let\m_syst_action_yes\syst_helpers_double_empty_one_yes
+% \let\m_syst_action_nop\syst_helpers_double_empty_one_nop
+% \let\if_next_blank_space_token\iffalse
+% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+%
+% \def\syst_helpers_double_empty_one_yes[#1]%
+% {\firstargumenttrue
+% \t_syst_aux{[{#1}]}% assignment
+% \let\m_syst_action_yes\syst_helpers_double_empty_two_yes
+% \let\m_syst_action_nop\syst_helpers_double_empty_two_nop
+% \let\if_next_blank_space_token\iffalse
+% \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+%
+% But we use this as it keeps the original name visible:
+
+\def\syst_helpers_empty_spaced_six {\the\t_syst_aux[][][][][][] }
+\def\syst_helpers_empty_normal_six {\the\t_syst_aux[][][][][][]}
+\def\syst_helpers_empty_spaced_five {\the\t_syst_aux[][][][][] }
+\def\syst_helpers_empty_normal_five {\the\t_syst_aux[][][][][]}
+\def\syst_helpers_empty_spaced_four {\the\t_syst_aux[][][][] }
+\def\syst_helpers_empty_normal_four {\the\t_syst_aux[][][][]}
+\def\syst_helpers_empty_spaced_three{\the\t_syst_aux[][][] }
+\def\syst_helpers_empty_normal_three{\the\t_syst_aux[][][]}
+\def\syst_helpers_empty_spaced_two {\the\t_syst_aux[][] }
+\def\syst_helpers_empty_normal_two {\the\t_syst_aux[][]}
+\def\syst_helpers_empty_spaced_one {\the\t_syst_aux[] }
+\def\syst_helpers_empty_normal_one {\the\t_syst_aux[]}
+
+\def\syst_helpers_single_empty_one_yes {\firstargumenttrue \the\t_syst_aux}
+\def\syst_helpers_double_empty_two_yes {\secondargumenttrue \the\t_syst_aux}
+\def\syst_helpers_triple_empty_three_yes {\thirdargumenttrue \the\t_syst_aux}
+\def\syst_helpers_quadruple_empty_four_yes {\fourthargumenttrue \the\t_syst_aux}
+\def\syst_helpers_quintuple_empty_five_yes {\fifthargumenttrue \the\t_syst_aux}
+\def\syst_helpers_sixtuple_empty_six_yes {\sixthargumenttrue \the\t_syst_aux}
+\def\syst_helpers_seventuple_empty_seven_yes{\seventhargumenttrue\the\t_syst_aux}
+
%D Single:
+% \unexpanded\def\dosingleempty#1%
+% {\syst_helpers_argument_reset
+% \doifelsenextoptional
+% {\firstargumenttrue#1}%
+% {\syst_helpers_single_empty_one_nop#1}}
+%
+% \def\syst_helpers_single_empty_one_nop#1%
+% {\firstargumentfalse
+% #1[]}
+
\unexpanded\def\dosingleempty#1%
{\syst_helpers_argument_reset
- \doifelsenextoptional
- {\firstargumenttrue#1}%
- {\syst_helpers_single_empty_one_nop#1}}
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_single_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_single_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_single_empty_one_nop#1%
+\def\syst_helpers_single_empty_one_nop
{\firstargumentfalse
- #1[]}
+ \the\t_syst_aux[]}
%D Double
+% \unexpanded\def\dodoubleempty#1%
+% {\syst_helpers_argument_reset
+% \doifelsenextoptional
+% {\syst_helpers_double_empty_one_yes#1}%
+% {\syst_helpers_double_empty_one_nop#1}}
+%
+% \def\syst_helpers_double_empty_one_yes#1[#2]%
+% {\firstargumenttrue
+% \doifelsenextoptional
+% {\secondargumenttrue#1[{#2}]}%
+% {\syst_helpers_double_empty_two_nop#1{#2}}}
+%
+% \def\syst_helpers_double_empty_one_nop#1%
+% {\firstargumentfalse
+% \secondargumentfalse
+% #1[][]}
+%
+% \def\syst_helpers_double_empty_two_nop
+% {\secondargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_double_empty_one_spaced
+% \else
+% \expandafter\syst_helpers_double_empty_one_normal
+% \fi}
+%
+% \def\syst_helpers_double_empty_one_spaced#1#2{#1[{#2}][] }
+% \def\syst_helpers_double_empty_one_normal#1#2{#1[{#2}][]}
+
\unexpanded\def\dodoubleempty#1%
{\syst_helpers_argument_reset
- \doifelsenextoptional
- {\syst_helpers_double_empty_one_yes#1}%
- {\syst_helpers_double_empty_one_nop#1}}
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_double_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_double_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_double_empty_one_yes#1[#2]%
+\def\syst_helpers_double_empty_one_yes[#1]%
{\firstargumenttrue
- \doifelsenextoptional
- {\secondargumenttrue#1[{#2}]}%
- {\syst_helpers_double_empty_two_nop#1{#2}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_double_empty_two_yes
+ \let\m_syst_action_nop\syst_helpers_double_empty_two_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_double_empty_one_nop#1%
+\def\syst_helpers_double_empty_one_nop
{\firstargumentfalse
\secondargumentfalse
- #1[][]}
+ \the\t_syst_aux[][]}
\def\syst_helpers_double_empty_two_nop
{\secondargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_double_empty_one_spaced
+ \expandafter\syst_helpers_empty_spaced_one
\else
- \expandafter\syst_helpers_double_empty_one_normal
+ \expandafter\syst_helpers_empty_normal_one
\fi}
-\def\syst_helpers_double_empty_one_spaced#1#2{#1[{#2}][] }
-\def\syst_helpers_double_empty_one_normal#1#2{#1[{#2}][]}
+% Triple
-% Three
+% \unexpanded\def\dotripleempty#1%
+% {\syst_helpers_argument_reset
+% \doifelsenextoptional
+% {\syst_helpers_triple_empty_one_yes#1}%
+% {\syst_helpers_triple_empty_one_nop#1}}
+%
+% \def\syst_helpers_triple_empty_one_yes#1[#2]%
+% {\firstargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_triple_empty_two_yes#1{#2}}%
+% {\syst_helpers_triple_empty_two_nop#1{#2}}}
+%
+% \def\syst_helpers_triple_empty_two_yes#1#2[#3]%
+% {\secondargumenttrue
+% \doifelsenextoptional
+% {\thirdargumenttrue#1[{#2}][{#3}]}%
+% {\syst_helpers_triple_empty_three_nop#1{#2}{#3}}}
+%
+% \def\syst_helpers_triple_empty_one_nop#1%
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% #1[][][]}
+%
+% \def\syst_helpers_triple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_triple_empty_two_spaced
+% \else
+% \expandafter\syst_helpers_triple_empty_two_normal
+% \fi}
+%
+% \def\syst_helpers_triple_empty_three_nop
+% {\thirdargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_triple_empty_three_spaced
+% \else
+% \expandafter\syst_helpers_triple_empty_three_normal
+% \fi}
+%
+% \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}][]}
\unexpanded\def\dotripleempty#1%
{\syst_helpers_argument_reset
- \doifelsenextoptional
- {\syst_helpers_triple_empty_one_yes#1}%
- {\syst_helpers_triple_empty_one_nop#1}}
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_triple_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_triple_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_triple_empty_one_yes#1[#2]%
+\def\syst_helpers_triple_empty_one_yes[#1]%
{\firstargumenttrue
- \doifelsenextoptional
- {\syst_helpers_triple_empty_two_yes#1{#2}}%
- {\syst_helpers_triple_empty_two_nop#1{#2}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_triple_empty_two_yes
+ \let\m_syst_action_nop\syst_helpers_triple_empty_two_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_triple_empty_two_yes#1#2[#3]%
+\def\syst_helpers_triple_empty_two_yes[#1]%
{\secondargumenttrue
- \doifelsenextoptional
- {\thirdargumenttrue#1[{#2}][{#3}]}%
- {\syst_helpers_triple_empty_three_nop#1{#2}{#3}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_triple_empty_three_yes
+ \let\m_syst_action_nop\syst_helpers_triple_empty_three_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_triple_empty_one_nop#1%
+\def\syst_helpers_triple_empty_one_nop
{\firstargumentfalse
\secondargumentfalse
\thirdargumentfalse
- #1[][][]}
+ \the\t_syst_aux[][][]}
\def\syst_helpers_triple_empty_two_nop
{\secondargumentfalse
\thirdargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_triple_empty_two_spaced
+ \expandafter\syst_helpers_empty_spaced_two
\else
- \expandafter\syst_helpers_triple_empty_two_normal
+ \expandafter\syst_helpers_empty_normal_two
\fi}
\def\syst_helpers_triple_empty_three_nop
{\thirdargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_triple_empty_three_spaced
+ \expandafter\syst_helpers_empty_spaced_one
\else
- \expandafter\syst_helpers_triple_empty_three_normal
+ \expandafter\syst_helpers_empty_normal_one
\fi}
-\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 Quadruple:
-%D Four:
+% \unexpanded\def\doquadrupleempty#1%
+% {\syst_helpers_argument_reset
+% \doifelsenextoptional
+% {\syst_helpers_quadruple_empty_one_yes#1}%
+% {\syst_helpers_quadruple_empty_one_nop#1}}
+%
+% \def\syst_helpers_quadruple_empty_one_yes#1[#2]%
+% {\firstargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_quadruple_empty_two_yes#1{#2}}%
+% {\syst_helpers_quadruple_empty_two_nop#1{#2}}}
+%
+% \def\syst_helpers_quadruple_empty_two_yes#1#2[#3]%
+% {\secondargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_quadruple_empty_three_yes#1{#2}{#3}}%
+% {\syst_helpers_quadruple_empty_three_nop#1{#2}{#3}}}
+%
+% \def\syst_helpers_quadruple_empty_three_yes#1#2#3[#4]%
+% {\thirdargumenttrue
+% \doifelsenextoptional
+% {\fourthargumenttrue#1[{#2}][{#3}][{#4}]}%
+% {\syst_helpers_quadruple_empty_four_nop#1{#2}{#3}{#4}}}
+%
+% \def\syst_helpers_quadruple_empty_one_nop#1%
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% #1[][][][]}
+%
+% \def\syst_helpers_quadruple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_quadruple_empty_two_spaced
+% \else
+% \expandafter\syst_helpers_quadruple_empty_two_normal
+% \fi}
+%
+% \def\syst_helpers_quadruple_empty_three_nop
+% {\thirdargumentfalse
+% \fourthargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_quadruple_empty_three_spaced
+% \else
+% \expandafter\syst_helpers_quadruple_empty_three_normal
+% \fi}
+%
+% \def\syst_helpers_quadruple_empty_four_nop
+% {\fourthargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_quadruple_empty_four_spaced
+% \else
+% \expandafter\syst_helpers_quadruple_empty_four_normal
+% \fi}
+%
+% \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}][]}
\unexpanded\def\doquadrupleempty#1%
{\syst_helpers_argument_reset
- \doifelsenextoptional
- {\syst_helpers_quadruple_empty_one_yes#1}%
- {\syst_helpers_quadruple_empty_one_nop#1}}
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_quadruple_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_quadruple_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_quadruple_empty_one_yes#1[#2]%
+\def\syst_helpers_quadruple_empty_one_yes[#1]%
{\firstargumenttrue
- \doifelsenextoptional
- {\syst_helpers_quadruple_empty_two_yes#1{#2}}%
- {\syst_helpers_quadruple_empty_two_nop#1{#2}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quadruple_empty_two_yes
+ \let\m_syst_action_nop\syst_helpers_quadruple_empty_two_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_quadruple_empty_two_yes#1#2[#3]%
+\def\syst_helpers_quadruple_empty_two_yes[#1]%
{\secondargumenttrue
- \doifelsenextoptional
- {\syst_helpers_quadruple_empty_three_yes#1{#2}{#3}}%
- {\syst_helpers_quadruple_empty_three_nop#1{#2}{#3}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quadruple_empty_three_yes
+ \let\m_syst_action_nop\syst_helpers_quadruple_empty_three_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_quadruple_empty_three_yes#1#2#3[#4]%
+\def\syst_helpers_quadruple_empty_three_yes[#1]%
{\thirdargumenttrue
- \doifelsenextoptional
- {\fourthargumenttrue#1[{#2}][{#3}][{#4}]}%
- {\syst_helpers_quadruple_empty_four_nop#1{#2}{#3}{#4}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quadruple_empty_four_yes
+ \let\m_syst_action_nop\syst_helpers_quadruple_empty_four_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_quadruple_empty_one_nop#1%
+\def\syst_helpers_quadruple_empty_one_nop
{\firstargumentfalse
\secondargumentfalse
\thirdargumentfalse
\fourthargumentfalse
- #1[][][][]}
+ \the\t_syst_aux[][][][]}
\def\syst_helpers_quadruple_empty_two_nop
{\secondargumentfalse
\thirdargumentfalse
\fourthargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_quadruple_empty_two_spaced
+ \expandafter\syst_helpers_empty_spaced_three
\else
- \expandafter\syst_helpers_quadruple_empty_two_normal
+ \expandafter\syst_helpers_empty_normal_three
\fi}
\def\syst_helpers_quadruple_empty_three_nop
{\thirdargumentfalse
\fourthargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_quadruple_empty_three_spaced
+ \expandafter\syst_helpers_empty_spaced_two
\else
- \expandafter\syst_helpers_quadruple_empty_three_normal
+ \expandafter\syst_helpers_empty_normal_two
\fi}
\def\syst_helpers_quadruple_empty_four_nop
{\fourthargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_quadruple_empty_four_spaced
+ \expandafter\syst_helpers_empty_spaced_one
\else
- \expandafter\syst_helpers_quadruple_empty_four_normal
+ \expandafter\syst_helpers_empty_normal_one
\fi}
-\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 Quintuple:
-%D Five:
+% \unexpanded\def\doquintupleempty#1%
+% {\syst_helpers_argument_reset
+% \doifelsenextoptional
+% {\syst_helpers_quintuple_empty_one_yes#1}%
+% {\syst_helpers_quintuple_empty_one_nop#1}}
+%
+% \def\syst_helpers_quintuple_empty_one_yes#1[#2]%
+% {\firstargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_quintuple_empty_two_yes#1{#2}}%
+% {\syst_helpers_quintuple_empty_two_nop#1{#2}}}
+%
+% \def\syst_helpers_quintuple_empty_two_yes#1#2[#3]%
+% {\secondargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_quintuple_empty_three_yes#1{#2}{#3}}%
+% {\syst_helpers_quintuple_empty_three_nop#1{#2}{#3}}}
+%
+% \def\syst_helpers_quintuple_empty_three_yes#1#2#3[#4]%
+% {\thirdargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_quintuple_empty_four_yes#1{#2}{#3}{#4}}%
+% {\syst_helpers_quintuple_empty_four_nop#1{#2}{#3}{#4}}}
+%
+% \def\syst_helpers_quintuple_empty_four_yes#1#2#3#4[#5]%
+% {\fourthargumenttrue
+% \doifelsenextoptional
+% {\fifthargumenttrue#1[{#2}][{#3}][{#4}][{#5}]}%
+% {\syst_helpers_quintuple_empty_five_nop#1{#2}{#3}{#4}{#5}}}
+%
+% \def\syst_helpers_quintuple_empty_one_nop#1%
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% #1[][][][][]}
+%
+% \def\syst_helpers_quintuple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_quintuple_empty_two_spaced
+% \else
+% \expandafter\syst_helpers_quintuple_empty_two_normal
+% \fi}
+%
+% \def\syst_helpers_quintuple_empty_three_nop
+% {\thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_quintuple_empty_three_spaced
+% \else
+% \expandafter\syst_helpers_quintuple_empty_three_normal
+% \fi}
+%
+% \def\syst_helpers_quintuple_empty_four_nop
+% {\fourthargumentfalse
+% \fifthargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_quintuple_empty_four_spaced
+% \else
+% \expandafter\syst_helpers_quintuple_empty_four_normal
+% \fi}
+%
+% \def\syst_helpers_quintuple_empty_five_nop
+% {\fifthargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_quintuple_empty_five_spaced
+% \else
+% \expandafter\syst_helpers_quintuple_empty_five_normal
+% \fi}
+%
+% \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}][]}
\unexpanded\def\doquintupleempty#1%
{\syst_helpers_argument_reset
- \doifelsenextoptional
- {\syst_helpers_quintuple_empty_one_yes#1}%
- {\syst_helpers_quintuple_empty_one_nop#1}}
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_quintuple_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_quintuple_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_quintuple_empty_one_yes#1[#2]%
+\def\syst_helpers_quintuple_empty_one_yes[#1]%
{\firstargumenttrue
- \doifelsenextoptional
- {\syst_helpers_quintuple_empty_two_yes#1{#2}}%
- {\syst_helpers_quintuple_empty_two_nop#1{#2}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quintuple_empty_two_yes
+ \let\m_syst_action_nop\syst_helpers_quintuple_empty_two_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_quintuple_empty_two_yes#1#2[#3]%
+\def\syst_helpers_quintuple_empty_two_yes[#1]%
{\secondargumenttrue
- \doifelsenextoptional
- {\syst_helpers_quintuple_empty_three_yes#1{#2}{#3}}%
- {\syst_helpers_quintuple_empty_three_nop#1{#2}{#3}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quintuple_empty_three_yes
+ \let\m_syst_action_nop\syst_helpers_quintuple_empty_three_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_quintuple_empty_three_yes#1#2#3[#4]%
+\def\syst_helpers_quintuple_empty_three_yes[#1]%
{\thirdargumenttrue
- \doifelsenextoptional
- {\syst_helpers_quintuple_empty_four_yes#1{#2}{#3}{#4}}%
- {\syst_helpers_quintuple_empty_four_nop#1{#2}{#3}{#4}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quintuple_empty_four_yes
+ \let\m_syst_action_nop\syst_helpers_quintuple_empty_four_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_quintuple_empty_four_yes#1#2#3#4[#5]%
+\def\syst_helpers_quintuple_empty_four_yes[#1]%
{\fourthargumenttrue
- \doifelsenextoptional
- {\fifthargumenttrue#1[{#2}][{#3}][{#4}][{#5}]}%
- {\syst_helpers_quintuple_empty_five_nop#1{#2}{#3}{#4}{#5}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_quintuple_empty_five_yes
+ \let\m_syst_action_nop\syst_helpers_quintuple_empty_five_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_quintuple_empty_one_nop#1%
+\def\syst_helpers_quintuple_empty_one_nop
{\firstargumentfalse
\secondargumentfalse
\thirdargumentfalse
\fourthargumentfalse
\fifthargumentfalse
- #1[][][][][]}
+ \the\t_syst_aux[][][][][]}
\def\syst_helpers_quintuple_empty_two_nop
{\secondargumentfalse
@@ -2446,9 +2811,9 @@
\fourthargumentfalse
\fifthargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_quintuple_empty_two_spaced
+ \expandafter\syst_helpers_empty_spaced_four
\else
- \expandafter\syst_helpers_quintuple_empty_two_normal
+ \expandafter\syst_helpers_empty_normal_four
\fi}
\def\syst_helpers_quintuple_empty_three_nop
@@ -2456,83 +2821,192 @@
\fourthargumentfalse
\fifthargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_quintuple_empty_three_spaced
+ \expandafter\syst_helpers_empty_spaced_three
\else
- \expandafter\syst_helpers_quintuple_empty_three_normal
+ \expandafter\syst_helpers_empty_normal_three
\fi}
\def\syst_helpers_quintuple_empty_four_nop
{\fourthargumentfalse
\fifthargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_quintuple_empty_four_spaced
+ \expandafter\syst_helpers_empty_spaced_two
\else
- \expandafter\syst_helpers_quintuple_empty_four_normal
+ \expandafter\syst_helpers_empty_normal_two
\fi}
\def\syst_helpers_quintuple_empty_five_nop
{\fifthargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_quintuple_empty_five_spaced
+ \expandafter\syst_helpers_empty_spaced_one
\else
- \expandafter\syst_helpers_quintuple_empty_five_normal
+ \expandafter\syst_helpers_empty_normal_one
\fi}
-\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 Sixtuple:
-%D Six
+% \unexpanded\def\dosixtupleempty#1%
+% {\syst_helpers_argument_reset
+% \doifelsenextoptional
+% {\syst_helpers_sixtuple_empty_one_yes#1}
+% {\syst_helpers_sixtuple_empty_one_nop#1}}
+%
+% \def\syst_helpers_sixtuple_empty_one_yes#1[#2]%
+% {\firstargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_sixtuple_empty_two_yes#1{#2}}%
+% {\syst_helpers_sixtuple_empty_two_nop#1{#2}}}
+%
+% \def\syst_helpers_sixtuple_empty_two_yes#1#2[#3]%
+% {\secondargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_sixtuple_empty_three_yes#1{#2}{#3}}%
+% {\syst_helpers_sixtuple_empty_three_nop#1{#2}{#3}}}
+%
+% \def\syst_helpers_sixtuple_empty_three_yes#1#2#3[#4]%
+% {\thirdargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_sixtuple_empty_four_yes#1{#2}{#3}{#4}}%
+% {\syst_helpers_sixtuple_empty_four_nop#1{#2}{#3}{#4}}}
+%
+% \def\syst_helpers_sixtuple_empty_four_yes#1#2#3#4[#5]%
+% {\fourthargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_sixtuple_empty_five_yes#1{#2}{#3}{#4}{#5}}%
+% {\syst_helpers_sixtuple_empty_five_nop#1{#2}{#3}{#4}{#5}}}
+%
+% \def\syst_helpers_sixtuple_empty_five_yes#1#2#3#4#5[#6]%
+% {\fifthargumenttrue
+% \doifelsenextoptional
+% {\sixthargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}]}%
+% {\syst_helpers_sixtuple_empty_six_nop#1{#2}{#3}{#4}{#5}{#6}}}
+%
+% \def\syst_helpers_sixtuple_empty_one_nop#1%
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% #1[][][][][][]}
+%
+% \def\syst_helpers_sixtuple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_sixtuple_empty_two_spaced
+% \else
+% \expandafter\syst_helpers_sixtuple_empty_two_normal
+% \fi}
+%
+% \def\syst_helpers_sixtuple_empty_three_nop
+% {\thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_sixtuple_empty_three_spaced
+% \else
+% \expandafter\syst_helpers_sixtuple_empty_three_normal
+% \fi}
+%
+% \def\syst_helpers_sixtuple_empty_four_nop
+% {\fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_sixtuple_empty_four_spaced
+% \else
+% \expandafter\syst_helpers_sixtuple_empty_four_normal
+% \fi}
+%
+% \def\syst_helpers_sixtuple_empty_five_nop
+% {\fifthargumentfalse
+% \sixthargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_sixtuple_empty_five_spaced
+% \else
+% \expandafter\syst_helpers_sixtuple_empty_five_normal
+% \fi}
+%
+% \def\syst_helpers_sixtuple_empty_six_nop
+% {\sixthargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_sixtuple_empty_six_spaced
+% \else
+% \expandafter\syst_helpers_sixtuple_empty_six_normal
+% \fi}
+%
+% \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}][]}
\unexpanded\def\dosixtupleempty#1%
{\syst_helpers_argument_reset
- \doifelsenextoptional
- {\syst_helpers_sixtuple_empty_one_yes#1}
- {\syst_helpers_sixtuple_empty_one_nop#1}}
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_sixtuple_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_sixtuple_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_sixtuple_empty_one_yes#1[#2]%
+\def\syst_helpers_sixtuple_empty_one_yes[#1]%
{\firstargumenttrue
- \doifelsenextoptional
- {\syst_helpers_sixtuple_empty_two_yes#1{#2}}%
- {\syst_helpers_sixtuple_empty_two_nop#1{#2}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_sixtuple_empty_two_yes
+ \let\m_syst_action_nop\syst_helpers_sixtuple_empty_two_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_sixtuple_empty_two_yes#1#2[#3]%
+\def\syst_helpers_sixtuple_empty_two_yes[#1]%
{\secondargumenttrue
- \doifelsenextoptional
- {\syst_helpers_sixtuple_empty_three_yes#1{#2}{#3}}%
- {\syst_helpers_sixtuple_empty_three_nop#1{#2}{#3}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_sixtuple_empty_three_yes
+ \let\m_syst_action_nop\syst_helpers_sixtuple_empty_three_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_sixtuple_empty_three_yes#1#2#3[#4]%
+\def\syst_helpers_sixtuple_empty_three_yes[#1]%
{\thirdargumenttrue
- \doifelsenextoptional
- {\syst_helpers_sixtuple_empty_four_yes#1{#2}{#3}{#4}}%
- {\syst_helpers_sixtuple_empty_four_nop#1{#2}{#3}{#4}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_sixtuple_empty_four_yes
+ \let\m_syst_action_nop\syst_helpers_sixtuple_empty_four_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_sixtuple_empty_four_yes#1#2#3#4[#5]%
+\def\syst_helpers_sixtuple_empty_four_yes[#1]%
{\fourthargumenttrue
- \doifelsenextoptional
- {\syst_helpers_sixtuple_empty_five_yes#1{#2}{#3}{#4}{#5}}%
- {\syst_helpers_sixtuple_empty_five_nop#1{#2}{#3}{#4}{#5}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_sixtuple_empty_five_yes
+ \let\m_syst_action_nop\syst_helpers_sixtuple_empty_five_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_sixtuple_empty_five_yes#1#2#3#4#5[#6]%
+\def\syst_helpers_sixtuple_empty_five_yes[#1]%
{\fifthargumenttrue
- \doifelsenextoptional
- {\sixthargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}]}%
- {\syst_helpers_sixtuple_empty_six_nop#1{#2}{#3}{#4}{#5}{#6}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_sixtuple_empty_six_yes
+ \let\m_syst_action_nop\syst_helpers_sixtuple_empty_six_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_sixtuple_empty_one_nop#1%
+\def\syst_helpers_sixtuple_empty_one_nop
{\firstargumentfalse
\secondargumentfalse
\thirdargumentfalse
\fourthargumentfalse
\fifthargumentfalse
\sixthargumentfalse
- #1[][][][][][]}
+ \the\t_syst_aux[][][][][][]}
\def\syst_helpers_sixtuple_empty_two_nop
{\secondargumentfalse
@@ -2541,9 +3015,9 @@
\fifthargumentfalse
\sixthargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_sixtuple_empty_two_spaced
+ \expandafter\syst_helpers_empty_spaced_five
\else
- \expandafter\syst_helpers_sixtuple_empty_two_normal
+ \expandafter\syst_helpers_empty_normal_five
\fi}
\def\syst_helpers_sixtuple_empty_three_nop
@@ -2552,9 +3026,9 @@
\fifthargumentfalse
\sixthargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_sixtuple_empty_three_spaced
+ \expandafter\syst_helpers_empty_spaced_four
\else
- \expandafter\syst_helpers_sixtuple_empty_three_normal
+ \expandafter\syst_helpers_empty_normal_four
\fi}
\def\syst_helpers_sixtuple_empty_four_nop
@@ -2562,84 +3036,215 @@
\fifthargumentfalse
\sixthargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_sixtuple_empty_four_spaced
+ \expandafter\syst_helpers_empty_spaced_three
\else
- \expandafter\syst_helpers_sixtuple_empty_four_normal
+ \expandafter\syst_helpers_empty_normal_three
\fi}
\def\syst_helpers_sixtuple_empty_five_nop
{\fifthargumentfalse
\sixthargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_sixtuple_empty_five_spaced
+ \expandafter\syst_helpers_empty_spaced_two
\else
- \expandafter\syst_helpers_sixtuple_empty_five_normal
+ \expandafter\syst_helpers_empty_normal_two
\fi}
\def\syst_helpers_sixtuple_empty_six_nop
{\sixthargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_sixtuple_empty_six_spaced
+ \expandafter\syst_helpers_empty_spaced_one
\else
- \expandafter\syst_helpers_sixtuple_empty_six_normal
+ \expandafter\syst_helpers_empty_normal_one
\fi}
-\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 Seventuple:
-%D Seven:
+% \unexpanded\def\doseventupleempty#1%
+% {\syst_helpers_argument_reset
+% \doifelsenextoptional
+% {\syst_helpers_seventuple_empty_one_yes#1}%
+% {\syst_helpers_seventuple_empty_one_nop#1}}
+%
+% \def\syst_helpers_seventuple_empty_one_yes#1[#2]%
+% {\firstargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_seventuple_empty_two_yes#1{#2}}%
+% {\syst_helpers_seventuple_empty_two_nop#1{#2}}}
+%
+% \def\syst_helpers_seventuple_empty_two_yes#1#2[#3]%
+% {\secondargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_seventuple_empty_three_yes#1{#2}{#3}}%
+% {\syst_helpers_seventuple_empty_three_nop#1{#2}{#3}}}
+%
+% \def\syst_helpers_seventuple_empty_three_yes#1#2#3[#4]%
+% {\thirdargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_seventuple_empty_four_yes#1{#2}{#3}{#4}}%
+% {\syst_helpers_seventuple_empty_four_nop#1{#2}{#3}{#4}}}
+%
+% \def\syst_helpers_seventuple_empty_four_yes#1#2#3#4[#5]%
+% {\fourthargumenttrue
+% \doifelsenextoptional
+% {\syst_helpers_seventuple_empty_five_yes#1{#2}{#3}{#4}{#5}}%
+% {\syst_helpers_seventuple_empty_five_nop#1{#2}{#3}{#4}{#5}}}
+%
+% \def\syst_helpers_seventuple_empty_five_yes#1#2#3#4#5[#6]%
+% {\fifthargumenttrue
+% \doifelsenextoptional
+% {\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\syst_helpers_seventuple_empty_six_yes#1#2#3#4#5#6[#7]%
+% {\sixthargumenttrue
+% \doifelsenextoptional
+% {\seventhargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}]}%
+% {\syst_helpers_seventuple_empty_seven_nop#1{#2}{#3}{#4}{#5}{#6}{#7}}}
+%
+% \def\syst_helpers_seventuple_empty_one_nop#1%
+% {\firstargumentfalse
+% \secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \seventhargumentfalse
+% #1[][][][][][][]}
+%
+% \def\syst_helpers_seventuple_empty_two_nop
+% {\secondargumentfalse
+% \thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \seventhargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_seventuple_empty_two_spaced
+% \else
+% \expandafter\syst_helpers_seventuple_empty_two_normal
+% \fi}
+%
+% \def\syst_helpers_seventuple_empty_three_nop
+% {\thirdargumentfalse
+% \fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \seventhargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_seventuple_empty_three_spaced
+% \else
+% \expandafter\syst_helpers_seventuple_empty_three_normal
+% \fi}
+%
+% \def\syst_helpers_seventuple_empty_four_nop
+% {\fourthargumentfalse
+% \fifthargumentfalse
+% \sixthargumentfalse
+% \seventhargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_seventuple_empty_four_spaced
+% \else
+% \expandafter\syst_helpers_seventuple_empty_four_normal
+% \fi}
+%
+% \def\syst_helpers_seventuple_empty_five_nop
+% {\fifthargumentfalse
+% \sixthargumentfalse
+% \seventhargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_seventuple_empty_five_spaced
+% \else
+% \expandafter\syst_helpers_seventuple_empty_five_normal
+% \fi}
+%
+% \def\syst_helpers_seventuple_empty_six_nop
+% {\sixthargumentfalse
+% \seventhargumentfalse
+% \if_next_blank_space_token
+% \expandafter\syst_helpers_seventuple_empty_six_spaced
+% \else
+% \expandafter\syst_helpers_seventuple_empty_six_normal
+% \fi}
+%
+% \def\syst_helpers_seventuple_empty_seven_nop
+% {\seventhargumentfalse
+% \if_next_blank_space_token
+% \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}][]}
\unexpanded\def\doseventupleempty#1%
{\syst_helpers_argument_reset
- \doifelsenextoptional
- {\syst_helpers_seventuple_empty_one_yes#1}%
- {\syst_helpers_seventuple_empty_one_nop#1}}
+ \t_syst_aux{#1}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_one_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_one_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_seventuple_empty_one_yes#1[#2]%
+\def\syst_helpers_seventuple_empty_one_yes[#1]%
{\firstargumenttrue
- \doifelsenextoptional
- {\syst_helpers_seventuple_empty_two_yes#1{#2}}%
- {\syst_helpers_seventuple_empty_two_nop#1{#2}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_two_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_two_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_seventuple_empty_two_yes#1#2[#3]%
+\def\syst_helpers_seventuple_empty_two_yes[#1]%
{\secondargumenttrue
- \doifelsenextoptional
- {\syst_helpers_seventuple_empty_three_yes#1{#2}{#3}}%
- {\syst_helpers_seventuple_empty_three_nop#1{#2}{#3}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_three_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_three_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_seventuple_empty_three_yes#1#2#3[#4]%
+\def\syst_helpers_seventuple_empty_three_yes[#1]%
{\thirdargumenttrue
- \doifelsenextoptional
- {\syst_helpers_seventuple_empty_four_yes#1{#2}{#3}{#4}}%
- {\syst_helpers_seventuple_empty_four_nop#1{#2}{#3}{#4}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_four_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_four_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_seventuple_empty_four_yes#1#2#3#4[#5]%
+\def\syst_helpers_seventuple_empty_four_yes[#1]%
{\fourthargumenttrue
- \doifelsenextoptional
- {\syst_helpers_seventuple_empty_five_yes#1{#2}{#3}{#4}{#5}}%
- {\syst_helpers_seventuple_empty_five_nop#1{#2}{#3}{#4}{#5}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_five_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_five_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_seventuple_empty_five_yes#1#2#3#4#5[#6]%
+\def\syst_helpers_seventuple_empty_five_yes[#1]%
{\fifthargumenttrue
- \doifelsenextoptional
- {\syst_helpers_seventuple_empty_six_yes#1{#2}{#3}{#4}{#5}{#6}}%
- {\syst_helpers_seventuple_empty_six_nop#1{#2}{#3}{#4}{#5}{#6}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_six_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_six_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_seventuple_empty_six_yes#1#2#3#4#5#6[#7]%
+\def\syst_helpers_seventuple_empty_six_yes[#1]%
{\sixthargumenttrue
- \doifelsenextoptional
- {\seventhargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}]}%
- {\syst_helpers_seventuple_empty_seven_nop#1{#2}{#3}{#4}{#5}{#6}{#7}}}
+ \toksapp\t_syst_aux{[{#1}]}%
+ \let\m_syst_action_yes\syst_helpers_seventuple_empty_seven_yes
+ \let\m_syst_action_nop\syst_helpers_seventuple_empty_seven_nop
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\syst_helpers_seventuple_empty_one_nop#1%
+\def\syst_helpers_seventuple_empty_one_nop
{\firstargumentfalse
\secondargumentfalse
\thirdargumentfalse
@@ -2647,7 +3252,7 @@
\fifthargumentfalse
\sixthargumentfalse
\seventhargumentfalse
- #1[][][][][][][]}
+ \the\t_syst_aux[][][][][][][]}
\def\syst_helpers_seventuple_empty_two_nop
{\secondargumentfalse
@@ -2657,9 +3262,9 @@
\sixthargumentfalse
\seventhargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_seventuple_empty_two_spaced
+ \expandafter\syst_helpers_empty_spaced_six
\else
- \expandafter\syst_helpers_seventuple_empty_two_normal
+ \expandafter\syst_helpers_empty_normal_six
\fi}
\def\syst_helpers_seventuple_empty_three_nop
@@ -2669,9 +3274,9 @@
\sixthargumentfalse
\seventhargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_seventuple_empty_three_spaced
+ \expandafter\syst_helpers_empty_spaced_five
\else
- \expandafter\syst_helpers_seventuple_empty_three_normal
+ \expandafter\syst_helpers_empty_normal_five
\fi}
\def\syst_helpers_seventuple_empty_four_nop
@@ -2680,9 +3285,9 @@
\sixthargumentfalse
\seventhargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_seventuple_empty_four_spaced
+ \expandafter\syst_helpers_empty_spaced_four
\else
- \expandafter\syst_helpers_seventuple_empty_four_normal
+ \expandafter\syst_helpers_empty_normal_four
\fi}
\def\syst_helpers_seventuple_empty_five_nop
@@ -2690,40 +3295,29 @@
\sixthargumentfalse
\seventhargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_seventuple_empty_five_spaced
+ \expandafter\syst_helpers_empty_spaced_three
\else
- \expandafter\syst_helpers_seventuple_empty_five_normal
+ \expandafter\syst_helpers_empty_normal_three
\fi}
\def\syst_helpers_seventuple_empty_six_nop
{\sixthargumentfalse
\seventhargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_seventuple_empty_six_spaced
+ \expandafter\syst_helpers_empty_spaced_two
\else
- \expandafter\syst_helpers_seventuple_empty_six_normal
+ \expandafter\syst_helpers_empty_normal_two
\fi}
\def\syst_helpers_seventuple_empty_seven_nop
{\seventhargumentfalse
\if_next_blank_space_token
- \expandafter\syst_helpers_seventuple_empty_seven_spaced
+ \expandafter\syst_helpers_empty_spaced_one
\else
- \expandafter\syst_helpers_seventuple_empty_seven_normal
+ \expandafter\syst_helpers_empty_normal_one
\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}][]}
+%D Aliases:
\let\dosingleargument \dosingleempty
\let\dodoubleargument \dodoubleempty
@@ -2900,7 +3494,7 @@
\begingroup
\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\\
+ \glet\syst_helpers_get_grouped_argument_e\\
\endgroup
\def\syst_helpers_get_grouped_argument_f
@@ -3031,13 +3625,13 @@
%D
%D Trivial:
-\unexpanded\def\letempty #1{\let#1\empty}
-\unexpanded\def\globalletempty#1{\global\let#1\empty}
+\unexpanded\def\letempty #1{\let #1\empty}
+\unexpanded\def\globalletempty#1{\glet#1\empty}
-\unexpanded\def\letvalueempty #1{\expandafter\let\csname#1\endcsname\empty}
-\unexpanded\def\letgvalueempty#1{\global\expandafter\let\csname#1\endcsname\empty}
-\unexpanded\def\letvaluerelax #1{\expandafter\let\csname#1\endcsname\relax}
-\unexpanded\def\letgvalurelax #1{\global\expandafter\let\csname#1\endcsname\relax}
+\unexpanded\def\letvalueempty #1{\expandafter\let \csname#1\endcsname\empty}
+\unexpanded\def\letgvalueempty#1{\expandafter\glet\csname#1\endcsname\empty}
+\unexpanded\def\letvaluerelax #1{\expandafter\let \csname#1\endcsname\relax}
+\unexpanded\def\letgvalurelax #1{\expandafter\glet\csname#1\endcsname\relax}
\unexpanded\def\relaxvalueifundefined#1%
{\ifcsname#1\endcsname \else
@@ -3183,17 +3777,25 @@
%D Apart from the prefixes, a few more \type{\expandafters}
%D are needed:
-\unexpanded\def\newif#1%
- {\privatescratchcounter\escapechar
- \escapechar\minusone
- \expandafter\expandafter\expandafter
- \redoglobal\expandafter\expandafter\expandafter
- \edef\@if#1{true}{\let\noexpand#1\noexpand\iftrue}%
- \expandafter\expandafter\expandafter
- \redoglobal\expandafter\expandafter\expandafter
- \edef\@if#1{false}{\let\noexpand#1\noexpand\iffalse}%
- \dodoglobal\@if#1{false}%
- \escapechar\privatescratchcounter}
+% \unexpanded\def\newif#1% uses the original plain \@if
+% {\privatescratchcounter\escapechar
+% \escapechar\minusone
+% \expandafter\expandafter\expandafter
+% \redoglobal\expandafter\expandafter\expandafter
+% \edef\@if#1{true}{\let\noexpand#1\noexpand\iftrue}%
+% \expandafter\expandafter\expandafter
+% \redoglobal\expandafter\expandafter\expandafter
+% \edef\@if#1{false}{\let\noexpand#1\noexpand\iffalse}%
+% \dodoglobal\@if#1{false}%
+% \escapechar\privatescratchcounter}
+
+\normalprotected\def\newif#1% see syst-ini.mkiv
+ {\let\new_if_saved\newif
+ \let\newif\new_if_check
+ \expandafter\redoglobal\expandafter\def\csname\expandafter\newif\csstring#1true\endcsname {\let#1\iftrue }%
+ \expandafter\redoglobal\expandafter\def\csname\expandafter\newif\csstring#1false\endcsname{\let#1\iffalse}%
+ \dodoglobal\csname\expandafter\newif\csstring#1false\endcsname
+ \let\newif\new_if_saved}
%D Also new:
@@ -3245,7 +3847,7 @@
% \bgroup \obeylines
%
-% \global\let\stoptexdefinition\relax
+% \glet\stoptexdefinition\relax
%
% \unexpanded\gdef\starttexdefinition%
% {\bgroup%
@@ -3302,7 +3904,7 @@
% \bgroup \obeylines
%
-% \global\let\stoptexdefinition\relax
+% \glet\stoptexdefinition\relax
%
% \unexpanded\gdef\starttexdefinition%
% {\bgroup%
@@ -3321,7 +3923,7 @@
\bgroup \obeylines
-\global\let\stoptexdefinition\relax
+\glet\stoptexdefinition\relax
\unexpanded\gdef\starttexdefinition%
{\bgroup%
@@ -3538,8 +4140,8 @@
\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{#4}%
- \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname{#4}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
\ifnum#3>\zerocount\relax
\ifnum#2<#1\relax
\let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
@@ -3567,7 +4169,7 @@
\fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}}
\unexpanded\def\syst_helpers_recurse_content
- {\csname\??recurseaction\recursedepth\endcsname}
+ {\csname\??recurseaction\the\outerrecurse\endcsname}
\unexpanded\def\syst_helpers_stepwise_recurse_yes
{\syst_helpers_recurse_content
@@ -3591,11 +4193,11 @@
{\syst_helpers_stepwise_recurse_nop\relax}
\unexpanded\def\syst_helpers_stepwise_recurse_nop#1#2#3#4%
- {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
+ {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname
\global\advance\outerrecurse\minusone}
% \unexpanded\def\nonostepwiserecurse#1#2#3%
-% {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
+% {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname
% \global\advance\outerrecurse\minusone}
\unexpanded\def\dorecurse#1%
@@ -3636,16 +4238,16 @@
\unexpanded\def\syst_helpers_recurse_x#1#2%
{\global\advance\outerrecurse \plusone
- \expandafter\gdef\csname\??recurseaction\recursedepth\endcsname{#2}%
- \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname{#2}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
\expandafter\syst_helpers_recurse_indeed\expandafter1\expandafter{\number#1}}
\unexpanded\def\syst_helpers_recurse_y#1#2%
{\global\advance\outerrecurse \plusone
- \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \expandafter\glet\csname\??recurseindex\the\outerrecurse\endcsname\recurselevel
\let\recurselevel\!!plusone
#2%
- \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
+ \expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname
\global\advance\outerrecurse \minusone}
\unexpanded\def\syst_helpers_recurse_indeed#1#2% from to
@@ -3670,7 +4272,7 @@
\syst_helpers_recurse_indeed}
\unexpanded\def\syst_helpers_recurse_indeed_nop#1#2#3%
- {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
+ {\expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname
\global\advance\outerrecurse \minusone }
%D \macros
@@ -3708,8 +4310,8 @@
\unexpanded\def\doloop#1%
{\global\advance\outerrecurse \plusone
- \expandafter\gdef\csname\??recurseaction\recursedepth\endcsname{#1}%
- \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname{#1}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
\let\endofloop\syst_helpers_loop
\syst_helpers_loop1} % no \plusone else \recurselevel wrong
@@ -3723,7 +4325,7 @@
\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
+ \expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\endcsname
\global\advance\outerrecurse\minusone}
\unexpanded\def\exitloop % \exitloop quits at end
@@ -3771,59 +4373,61 @@
%D \stoptyping
\def\syst_helpers_recurse_content
- {\csname\??recurseaction\recursedepth\expandafter\expandafter\expandafter\endcsname
- \expandafter\expandafter\expandafter{\expandafter\recurselevel\expandafter}\expandafter{\recursedepth}}
+ {\csname\??recurseaction\the\outerrecurse\expandafter\expandafter\expandafter\endcsname
+ \expandafter\expandafter\expandafter{\expandafter\recurselevel\expandafter}\expandafter{\the\outerrecurse}}
\unexpanded\def\syst_helpers_recurse_x#1#2%
{\global\advance\outerrecurse \plusone
- \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#2}%
- \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#2}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
\expandafter\syst_helpers_recurse_indeed\expandafter1\expandafter{\number#1}}
\unexpanded\def\syst_helpers_recurse_y#1#2%
{\global\advance\outerrecurse \plusone
- \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
\let\recurselevel\!!plusone
- \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#2}%
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#2}%
\syst_helpers_recurse_content
- \expandafter\let\expandafter\recurselevel\csname\??recurseindex\recursedepth\endcsname
+ \expandafter\let\expandafter\recurselevel\csname\??recurseindex\the\outerrecurse\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\??recurseaction\recursedepth\endcsname##1##2{#4}%
- \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
- \ifnum#3>\zerocount\relax
- \ifnum#2<#1\relax
- \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
- \else
- \let\syst_helpers_stepwise_next\syst_helpers_stepwise_recurse
- \fi
- \else
- \ifnum#3<\zerocount\relax
- \ifnum#1<#2\relax
- \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
- \else
- \let\syst_helpers_stepwise_next\syst_helpers_stepwise_reverse
- \fi
- \else
- \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
- \fi
- \fi\normalexpanded{\syst_helpers_stepwise_next{\number#1}{\number#2}{\number#3}}}
-
\unexpanded\def\doloop#1%
{\global\advance\outerrecurse \plusone
- \global\expandafter\def\csname\??recurseaction\recursedepth\endcsname##1##2{#1}%
- \global\expandafter\let\csname\??recurseindex\recursedepth\endcsname\recurselevel
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#1}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
\let\endofloop\syst_helpers_loop
\syst_helpers_loop1} % no \plusone else \recurselevel wrong
-% faster
-
+% for instance:
+%
+% \unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+% {\global\advance\outerrecurse \plusone
+% \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#4}%
+% \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
+% \ifnum#3>\zerocount\relax
+% \ifnum#2<#1\relax
+% \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
+% \else
+% \let\syst_helpers_stepwise_next\syst_helpers_stepwise_recurse
+% \fi
+% \else
+% \ifnum#3<\zerocount\relax
+% \ifnum#1<#2\relax
+% \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
+% \else
+% \let\syst_helpers_stepwise_next\syst_helpers_stepwise_reverse
+% \fi
+% \else
+% \let\syst_helpers_stepwise_next\syst_helpers_stepwise_exit
+% \fi
+% \fi\normalexpanded{\syst_helpers_stepwise_next{\number#1}{\number#2}{\number#3}}}
+%
+% 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
+% \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#4}%
+% \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
% \csname @swr%
% \ifnum#3>\zerocount
% \ifnum#2<#1\else d\fi
@@ -3831,17 +4435,19 @@
% \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
+%
+% nicer:
\installsystemnamespace{recursestepwise}
\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
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#4}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
\csname\??recursestepwise
% we need the x in order to avoid the \relax that tex adds
\ifnum#3>\zerocount
@@ -3860,8 +4466,8 @@
%
% \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
+% \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1##2{#4}%
+% \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recurselevel
% \normalexpanded
% {\ifnum#3>\zerocount
% \ifnum#2<#1
@@ -3936,10 +4542,10 @@
\unexpanded\def\doloopoverlist#1#2%
{\global\advance\outerrecurse\plusone
- \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
+ \expandafter\gdef\csname\??recurseaction\the\outerrecurse\endcsname##1{\edef\recursestring{##1}#2}%
+ \expandafter\glet\csname\??recurseindex \the\outerrecurse\endcsname\recursestring
+ \normalexpanded{\processcommalist[#1]{\expandafter\noexpand\csname\??recurseaction\the\outerrecurse\endcsname}}%
+ \expandafter\let\expandafter\recursestring\csname\??recurseindex\the\outerrecurse\endcsname
\global\advance\outerrecurse\minusone}
%D \macros
@@ -4113,14 +4719,22 @@
\def\syst_helpers_check_if_assignment_else#1=#2#3\_e_o_p_{\if#2@}%
-\unexpanded\def\doifelseassignment#1% expandable
+\unexpanded\def\doifelseassignment#1%
{\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=@@\_e_o_p_
\expandafter\secondoftwoarguments
\else
\expandafter\firstoftwoarguments
\fi}
-\let\doifassignmentelse\doifelseassignment
+\unexpanded\def\doifelseassignmentcs#1#2#3%
+ {\expandafter\syst_helpers_check_if_assignment_else\detokenize{#1}=@@\_e_o_p_
+ \expandafter#3%
+ \else
+ \expandafter#2%
+ \fi}
+
+\let\doifassignmentelse \doifelseassignment
+\let\doifassignmentelsecs\doifelseassignmentcs
\newif\ifassignment
@@ -4415,16 +5029,14 @@
%D \def\doezomaarwat#1{....#1....}
%D \stoptyping
%D
-%D A disadvantage of this approach is that the tokens that
-%D form \type{#1} are fixed the the moment the argument is read
-%D in. Normally this is no problem, but for instance verbatim
-%D environments adapt the \CATCODES\ of characters and therefore
+%D A disadvantage of this approach is that the tokens that form \type{#1} are fixed
+%D the the moment the argument is read in. Normally this is no problem, but for
+%D instance verbatim environments adapt the \CATCODES\ of characters and therefore
%D are not always happy with already fixed tokens.
%D
-%D Another problem arises when the argument is grouped not by
-%D \type{{}} but by \type{\bgroup} and \type{\egroup}. Such an
-%D argument fails, because the \type{\bgroup} is een as the
-%D argument (which is quite normal).
+%D Another problem arises when the argument is grouped not by \type {{}} but by
+%D \type {\bgroup} and \type {\egroup}. Such an argument fails, because the \type
+%D {\bgroup} is een as the argument (which is quite normal).
%D
%D The next macro offers a solution for both unwanted
%D situations:
@@ -4454,9 +5066,8 @@
%D .......... \rightword{the right way}
%D \stoptyping
%D
-%D Here \TEX\ typesets \type{\bf the right way} unbreakable
-%D at the end of the line. The solution mentioned before does
-%D not work here. We also handle
+%D Here \TEX\ typesets \type {\bf the right way} unbreakable at the end of the line.
+%D The solution mentioned before does not work here. We also handle
%D
%D \starttyping
%D to be \bold{bold} or not, that's the question
@@ -4485,80 +5096,150 @@
% \afterassignment\m_syst_helpers_handle_group_before
% \let\next=}
-\unexpanded\def\syst_helpers_handle_group_normal#1#2%
+% \unexpanded\def\syst_helpers_handle_group_normal#1#2%
+% {\bgroup
+% \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\m_syst_helpers_handle_group_normal_before
+% {\bgroup
+% \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}
+%
+% \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\m_syst_helpers_handle_group_simple_before
+% {\bgroup
+% \aftergroup\m_syst_helpers_handle_group_simple_after
+% \m_syst_helpers_handle_group_before}
+%
+% \def\m_syst_helpers_handle_group_simple_after
+% {\m_syst_helpers_handle_group_after
+% \egroup}%
+%
+% \unexpanded\def\syst_helpers_handle_group_pickup#1#2#3% no inner group (so no kerning interference)
+% {\bgroup
+% \def\m_syst_helpers_handle_group_before{#1}%
+% \def\m_syst_helpers_handle_group_after {#2\egroup#3}%
+% \afterassignment\m_syst_helpers_handle_group_pickup_before
+% \let\next=}
+%
+% \def\m_syst_helpers_handle_group_pickup_before
+% {\bgroup
+% \aftergroup\m_syst_helpers_handle_group_after
+% \m_syst_helpers_handle_group_before}
+%
+% \unexpanded\def\syst_helpers_handle_group_nop
+% {\ifnum\currentgrouptype=\semisimplegroupcode
+% \expandafter\syst_helpers_handle_group_nop_a
+% \else
+% \expandafter\syst_helpers_handle_group_nop_b
+% \fi}
+%
+% \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\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}
+
+\unexpanded\def\syst_helpers_handle_group_nop
+ {\ifnum\currentgrouptype=\semisimplegroupcode
+ \expandafter\syst_helpers_handle_group_nop_a
+ \else
+ \expandafter\syst_helpers_handle_group_nop_b
+ \fi}
+
+\def\syst_helpers_handle_group_nop_a
+ {\begingroup
+ \aftergroup\m_syst_helpers_handle_group_a
+ \aftergroup\endgroup
+ \m_syst_helpers_handle_group_b}
+
+\def\syst_helpers_handle_group_nop_b
+ {\bgroup
+ \aftergroup\m_syst_helpers_handle_group_a
+ \aftergroup\egroup
+ \m_syst_helpers_handle_group_b}
+
+\unexpanded\def\syst_helpers_handle_group_normal
{\bgroup
- \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\m_syst_helpers_handle_group_normal_before
{\bgroup
- \m_syst_helpers_handle_group_before
+ \m_syst_helpers_handle_group_b
\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=}
+ \aftergroup\m_syst_helpers_handle_group_a
+ \aftergroup\egroup
+ \aftergroup\egroup}
-\unexpanded\def\syst_helpers_handle_group_simple#1#2% no inner group (so no kerning interference)
+\unexpanded\def\syst_helpers_handle_group_simple% 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\m_syst_helpers_handle_group_simple_before
{\bgroup
\aftergroup\m_syst_helpers_handle_group_simple_after
- \m_syst_helpers_handle_group_before}
+ \m_syst_helpers_handle_group_b}
\def\m_syst_helpers_handle_group_simple_after
- {\m_syst_helpers_handle_group_after
+ {\m_syst_helpers_handle_group_a
\egroup}%
-\unexpanded\def\syst_helpers_handle_group_pickup#1#2#3% no inner group (so no kerning interference)
+\unexpanded\def\syst_helpers_handle_group_pickup% no inner group (so no kerning interference)
{\bgroup
- \def\m_syst_helpers_handle_group_before{#1}%
- \def\m_syst_helpers_handle_group_after {#2\egroup#3}%
\afterassignment\m_syst_helpers_handle_group_pickup_before
\let\next=}
\def\m_syst_helpers_handle_group_pickup_before
{\bgroup
- \aftergroup\m_syst_helpers_handle_group_after
- \m_syst_helpers_handle_group_before}
+ \aftergroup\m_syst_helpers_handle_group_a
+ \aftergroup\egroup
+ \aftergroup\m_syst_helpers_handle_group_p
+ \m_syst_helpers_handle_group_b}
-\unexpanded\def\syst_helpers_handle_group_nop
+\unexpanded\def\syst_helpers_handle_group_nop_x
{\ifnum\currentgrouptype=\semisimplegroupcode
- \expandafter\syst_helpers_handle_group_nop_a
+ \begingroup
+ \aftergroup\endgroup
\else
- \expandafter\syst_helpers_handle_group_nop_b
- \fi}
+ \bgroup
+ \aftergroup\egroup
+ \fi
+ \m_syst_helpers_handle_group_b}
-\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}
+\unexpanded\def\syst_helpers_handle_group_normal_x
+ {\bgroup
+ \afterassignment\m_syst_helpers_handle_group_normal_before_x
+ \let\next=}
-\def\syst_helpers_handle_group_nop_b#1#2%
- {\def\m_syst_helpers_handle_group_after{#2\egroup}%
+\def\m_syst_helpers_handle_group_normal_before_x
+ {\bgroup
+ \m_syst_helpers_handle_group_b
\bgroup
- \aftergroup\m_syst_helpers_handle_group_after
- #1}
+ \aftergroup\egroup
+ \aftergroup\egroup}
%D I considered it a nuisance that
%D
@@ -4567,25 +5248,61 @@
%D {as grass}
%D \stoptyping
%D
-%D was not interpreted as one would expect. This is due to the
-%D fact that \type{\futurelet} obeys blank spaces, and a
-%D line||ending token is treated as a blank space. So the final
-%D implementation became:
+%D was not interpreted as one would expect. This is due to the fact that \type
+%D {\futurelet} obeys blank spaces, and a line||ending token is treated as a blank
+%D space. So the final implementation became:
+
+% \unexpanded\def\groupedcommand#1#2%
+% {\doifelsenextbgroup{\syst_helpers_handle_group_normal{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}}
+%
+% \unexpanded\def\groupedcommandcs#1#2%
+% {\doifelsenextbgroup{\syst_helpers_handle_group_normal{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}}
+%
+% \unexpanded\def\triggergroupedcommand#1%
+% {\doifelsenextbgroup{\syst_helpers_handle_group_normal{#1}{}}{\syst_helpers_handle_group_nop{#1}{}}}
+%
+% \unexpanded\def\triggergroupedcommandcs#1%
+% {\doifelsenextbgroup{\syst_helpers_handle_group_normal{#1}{}}{\syst_helpers_handle_group_nop{#1}{}}}
+%
+% \unexpanded\def\simplegroupedcommand#1#2%
+% {\doifelsenextbgroup{\syst_helpers_handle_group_simple{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}}
+%
+% \unexpanded\def\pickupgroupedcommand#1#2#3%
+% {\doifelsenextbgroup{\syst_helpers_handle_group_pickup{#1}{#2}{#3}}{\syst_helpers_handle_group_nop{#1}{#2}}}
\unexpanded\def\groupedcommand#1#2%
- {\doifelsenextbgroup{\syst_helpers_handle_group_normal{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}}
+ {\def\m_syst_helpers_handle_group_b{#1}%
+ \def\m_syst_helpers_handle_group_a{#2}%
+ \doifelsenextbgroupcs\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop}
+
+\unexpanded\def\groupedcommandcs#1#2%
+ {\let\m_syst_helpers_handle_group_b#1%
+ \let\m_syst_helpers_handle_group_a#2%
+ \doifelsenextbgroupcs\syst_helpers_handle_group_normal\syst_helpers_handle_group_nop}
\unexpanded\def\simplegroupedcommand#1#2%
- {\doifelsenextbgroup{\syst_helpers_handle_group_simple{#1}{#2}}{\syst_helpers_handle_group_nop{#1}{#2}}}
+ {\def\m_syst_helpers_handle_group_b{#1}%
+ \def\m_syst_helpers_handle_group_a{#2}%
+ \doifelsenextbgroupcs\syst_helpers_handle_group_simple\syst_helpers_handle_group_nop}
\unexpanded\def\pickupgroupedcommand#1#2#3%
- {\doifelsenextbgroup{\syst_helpers_handle_group_pickup{#1}{#2}{#3}}{\syst_helpers_handle_group_nop{#1}{#2}}}
+ {\def\m_syst_helpers_handle_group_b{#1}%
+ \def\m_syst_helpers_handle_group_a{#2}%
+ \def\m_syst_helpers_handle_group_p{#2}%
+ \doifelsenextbgroupcs\syst_helpers_handle_group_pickup\syst_helpers_handle_group_nop}
-%D Users should be aware of the fact that grouping can
-%D interfere with ones paragraph settings that are executed
-%D after the paragraph is closed. One should therefore
-%D explictly close the paragraph with \type{\par}, else the
-%D settings will be forgotten and not applied. So it's:
+\unexpanded\def\triggergroupedcommand#1%
+ {\def\m_syst_helpers_handle_group_b{#1}%
+ \doifelsenextbgroupcs\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x}
+
+\unexpanded\def\triggergroupedcommandcs#1%
+ {\let\m_syst_helpers_handle_group_b#1%
+ \doifelsenextbgroupcs\syst_helpers_handle_group_normal_x\syst_helpers_handle_group_nop_x}
+
+%D Users should be aware of the fact that grouping can interfere with ones paragraph
+%D settings that are executed after the paragraph is closed. One should therefore
+%D explictly close the paragraph with \type {\par}, else the settings will be
+%D forgotten and not applied. So it's:
%D
%D \starttyping
%D \def\BoldRaggedCenter%
@@ -5392,7 +6109,7 @@
\fi}
\unexpanded\def\globalprocesscommalist[#1]#2%
- {\global\let\m_syst_helpers_comma_list_command_global#2%
+ {\glet\m_syst_helpers_comma_list_command_global#2%
\expandafter\syst_helpers_comma_list_command_global_step#1,],}
%D \macros
@@ -5454,9 +6171,9 @@
\unexpanded\def\swapcounts#1#2{\c_syst_helpers_swapped #1\relax#1#2\relax#2\c_syst_helpers_swapped}
\unexpanded\def\swapmacros#1#2{\let\m_syst_helpers_swapped#1\let #1#2\let #2\m_syst_helpers_swapped}
-\unexpanded\def\globalswapdimens#1#2{\d_syst_helpers_swapped #1\global #1#2\global #2\d_syst_helpers_swapped}
-\unexpanded\def\globalswapcounts#1#2{\c_syst_helpers_swapped #1\global #1#2\global #2\c_syst_helpers_swapped}
-\unexpanded\def\globalswapmacros#1#2{\let\m_syst_helpers_swapped#1\global\let#1#2\global\let#2\m_syst_helpers_swapped}
+\unexpanded\def\globalswapdimens#1#2{\d_syst_helpers_swapped #1\global#1#2\global#2\d_syst_helpers_swapped}
+\unexpanded\def\globalswapcounts#1#2{\c_syst_helpers_swapped #1\global#1#2\global#2\c_syst_helpers_swapped}
+\unexpanded\def\globalswapmacros#1#2{\let\m_syst_helpers_swapped#1\glet #1#2\glet #2\m_syst_helpers_swapped}
%D \macros
%D {pushmacro,popmacro}
@@ -5481,11 +6198,11 @@
% \expandafter\newcount\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
% \fi
% \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}
+% \expandafter\glet\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
+% \expandafter\glet\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
@@ -5494,7 +6211,7 @@
% \expandafter\newcount\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname
% \fi
% \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}
+% \expandafter\glet\csname\the\csname\??localpushedmacro\m_syst_helpers_push_macro\endcsname\m_syst_helpers_push_macro\endcsname#1}
%
% \unexpanded\def\localpopmacro#1%
% {\xdef\m_syst_helpers_push_macro{\string#1}%
@@ -5505,6 +6222,8 @@
% \let\popmacro \localpopmacro
%
% slightly faster but more important: less tracing
+%
+% possible optimization \installmacrostack\foo: \syst_push_foo \syst_pop_foo
\let\m_syst_helpers_push_macro\empty
@@ -5525,7 +6244,7 @@
\else
\syst_helpers_push_macro_new_global
\fi
- \global\expandafter\let\csname\the\lastnamedcs\m_syst_helpers_push_macro\endcsname#1}
+ \expandafter\glet\csname\the\lastnamedcs\m_syst_helpers_push_macro\endcsname#1}
\unexpanded\def\localpushmacro#1% this one can be used to push a value over an \egroup
{\xdef\m_syst_helpers_push_macro{\csstring#1}%
@@ -5534,13 +6253,13 @@
\else
\syst_helpers_push_macro_new_local
\fi
- \global\expandafter\let\csname\the\lastnamedcs\m_syst_helpers_push_macro\endcsname#1}
+ \expandafter\glet\csname\the\lastnamedcs\m_syst_helpers_push_macro\endcsname#1}
\unexpanded\def\globalpopmacro#1%
{\xdef\m_syst_helpers_push_macro{\csstring#1}%
\c_syst_helpers_pop_count\csname\??globalpushedmacro\m_syst_helpers_push_macro\endcsname
\global\advance\lastnamedcs \minusone
- \global\expandafter\let\expandafter#1\csname\the\c_syst_helpers_pop_count\m_syst_helpers_push_macro\endcsname}
+ \expandafter\glet\expandafter#1\csname\the\c_syst_helpers_pop_count\m_syst_helpers_push_macro\endcsname}
\unexpanded\def\localpopmacro#1%
{\xdef\m_syst_helpers_push_macro{\csstring#1}%
@@ -6060,7 +6779,7 @@
\unexpanded\def\processassignlist#1[#2]#3%
{\def\syst_helpers_process_assign_list_assign[##1=##2=##3]%
- {\doifnot{##3}\relax{#3{##1}}}%
+ {\doif{##3}\relax{#3{##1}}}%
\def\syst_helpers_process_assign_list_step##1%
{\syst_helpers_process_assign_list_assign[##1==\relax]}%
\processcommalist[#2]\syst_helpers_process_assign_list_step}
@@ -6996,14 +7715,6 @@
{\unprotect
\syst_helpers_unprotected}
-% awaiting the definitive implementation
-
-% \ifdefined\resettimer \else
-% \let\resettimer \relax
-% \newcount\elapsedtime
-% \fi
-% \def\elapsedseconds{\expandafter\withoutpt\the\dimexpr\elapsedtime sp\relax}
-
\let\resettimer \clf_resettimer
\let\elapsedtime \clf_elapsedtime
\let\elapsedseconds \elapsedtime
@@ -7172,6 +7883,12 @@
\unexpanded\def\signalcharacter{\char\zerocount} % \zwj
+% \unexpanded\def\signalcharacter
+% {\scratchcounter\normallanguage
+% \normallanguage\zerocount
+% \char\zerocount
+% \normallanguage\scratchcounter}
+
%D A few secial variants of commands defined here. Some more will be moved here (e.g.
%D from table modules.
@@ -7486,3 +8203,23 @@
% \edef\tempstring{\the#1}%
% \tx\ttbf\string#1: \tttf\meaning\tempstring
% \endgroup}
+
+%D Not needed now, but more efficient that expanding
+%
+% \chardef\_E_O_T_0
+%
+% \unexpanded\def\doifelsetokens#1%
+% {\dodoifelsetokens#1\_E_O_T_\_e_o_t_}
+%
+% \def\dodoifelsetokens#1#2\_e_o_t_
+% {\ifx#1\_E_O_T_
+% \expandafter\secondoftwoarguments
+% \else
+% \expandafter\firstoftwoarguments
+% \fi}
+%
+% \def\emptytokscondition#1%
+% {\doemptytokscondition#1\_E_O_T_\_e_o_t_}
+%
+% \def\doemptytokscondition#1#2\_e_o_t_
+% {\ifx#1\_E_O_T_}
diff --git a/tex/context/base/mkiv/syst-cmp.lua b/tex/context/base/mkiv/syst-cmp.lua
new file mode 100644
index 000000000..67595d043
--- /dev/null
+++ b/tex/context/base/mkiv/syst-cmp.lua
@@ -0,0 +1,8 @@
+if not modules then modules = { } end modules ['syst-cmp'] = {
+ version = 1.001,
+ comment = "companion to syst-cmp.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
diff --git a/tex/context/base/mkiv/syst-cmp.mkiv b/tex/context/base/mkiv/syst-cmp.mkiv
new file mode 100644
index 000000000..a5ebdd8e3
--- /dev/null
+++ b/tex/context/base/mkiv/syst-cmp.mkiv
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=syst-cmp,
+%D version=2018.12.05,
+%D title=\CONTEXT\ System Macros,
+%D subtitle=Compatibility,
+%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 Some code that has been laying around for generic compatibility is (and will be)
+%D moved here, for instance because tikz needs it. At some point I will make an
+%D indirect interface for generic code (if needed).
+
+\registerctxluafile{syst-cmp}{}
+
+\unprotect
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/syst-ini.mkiv b/tex/context/base/mkiv/syst-ini.mkiv
index 4b5cc616b..7ce48c79f 100644
--- a/tex/context/base/mkiv/syst-ini.mkiv
+++ b/tex/context/base/mkiv/syst-ini.mkiv
@@ -19,116 +19,124 @@
%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
-
-\catcode`\{ = 1 % left brace is begin-group character
-\catcode`\} = 2 % right brace is end-group character
-\catcode`\$ = 3 % dollar sign is math shift
-\catcode`\& = 4 % ampersand is alignment tab
-\catcode`\# = 6 % hash mark is macro parameter character
-\catcode`\^ = 7 % circumflex and uparrow are for superscripts
-\catcode`\_ = 8 % underline and downarrow are for subscripts
-\catcode`\^^I = 10 % ascii tab is a blank space
-
-%catcode`\^^M = 5 % ascii return is end-line
-%catcode`\% = 14 % percent sign is comment character
-%catcode`\ = 10 % ascii space is blank space
-%catcode`\^^? = 15 % ascii delete is invalid
-
-\catcode`\~ = 13 % tilde is active
-\catcode`\^^L = 13 % ascii form-feed
-
-%catcode`\A = 11
-%.......
-%catcode`\Z = 11
-
-%catcode`\a = 11
-%.......
-%catcode`\z = 11
-
-\def ^^L{\par}
-\def\^^M{\ } % control <return> = control <space>
-\def\^^I{\ } % same for <tab>
-
-%D In \CONTEXT, we simply ignore end||of||file tokens:
-
-\catcode`\^^Z=9
-
-%D It makes sense to know what engine we're running so let's try to deduce it.
-
-\chardef\unknownengine = 0
-\chardef\pdftexengine = 1
-\chardef\xetexengine = 2
-\chardef\luatexengine = 3
-
-\chardef\statuswrite = 128
-
-\ifx\directlua\undefined
- \ifx\XeTeXversion\undefined
- \ifx\pdftexversion\undefined
- \let\texengine\unknownengine
- \else
- \let\texengine\pdftexengine
- \fi
- \else
- \let\texengine\xetexengine
- \fi
-\else
- \let\texengine\luatexengine
-\fi
-
-\ifnum\texengine=\luatexengine
- % for historic reasons we keep some mkii code around
-\else
- \immediate\write\statuswrite{>>>}
- \immediate\write\statuswrite{>>> only luatex is supported}
- \immediate\write\statuswrite{>>>}
- \let\dump\relax
- \expandafter\end
-\fi
+%D
+%D First we define a bunch of constants. Normally we would \type {\setconstant}
+%D but we're prestine and have no macros defined yet. Abstraction also makes it
+%D possible to avoid the \type {^^} in the input.
+
+\chardef\escapecatcode 0
+\chardef\begingroupcatcode 1
+\chardef\endgroupcatcode 2
+\chardef\mathshiftcatcode 3
+\chardef\alignmentcatcode 4
+\chardef\endoflinecatcode 5
+\chardef\parametercatcode 6
+\chardef\superscriptcatcode 7
+\chardef\subscriptcatcode 8
+\chardef\ignorecatcode 9
+\chardef\spacecatcode 10
+\chardef\lettercatcode 11
+\chardef\othercatcode 12 % finally obsolete: \let\other \othercatcode
+\chardef\activecatcode 13 % finally obsolete: \let\active\activecatcode
+\chardef\commentcatcode 14
+\chardef\invalidcatcode 15
+
+%chardef\zeroasciicode 0
+\chardef\tabasciicode 9
+\chardef\newlineasciicode 10 % don't confuse this one with \endoflineasciicode
+\chardef\formfeedasciicode 12
+\chardef\endoflineasciicode 13 % somewhat messy but this can be the active \par
+\chardef\endoffileasciicode 26
+\chardef\spaceasciicode 32
+\chardef\exclamationmarkasciicode 33 % ! used in namespace protection
+\chardef\doublequoteasciicode 34 % "
+\chardef\hashasciicode 35
+\chardef\dollarasciicode 36
+\chardef\commentasciicode 37
+\chardef\ampersandasciicode 38
+\chardef\singlequoteasciicode 39 % '
+\chardef\primeasciicode 39 % '
+\chardef\leftparentasciicode 40
+\chardef\rightparentasciicode 41
+\chardef\hyphenasciicode 45
+\chardef\forwardslashasciicode 47 % /
+\chardef\colonasciicode 58
+\chardef\lessthanasciicode 60 % < used as alternative verbatim {
+\chardef\morethanasciicode 62 % > used as alternative verbatim }
+\chardef\questionmarkasciicode 63 % ? used in namespace protection
+\chardef\atsignasciicode 64 % @ used in namespace protection
+\chardef\backslashasciicode 92 % `\\
+\chardef\circumflexasciicode 94
+\chardef\underscoreasciicode 95
+\chardef\leftbraceasciicode 123 % `\{
+\chardef\barasciicode 124 % `\|
+\chardef\rightbraceasciicode 125 % `\}
+\chardef\tildeasciicode 126 % `\~
+\chardef\delasciicode 127
+
+%catcode\zeroasciicode \ignorecatcode % `\^^@ ascii null is ignored
+\catcode\tabasciicode \spacecatcode % `\^^I ascii tab is a blank space
+\catcode\formfeedasciicode \activecatcode % `\^^L ascii form-feed (active, set later)
+%catcode\endoflineasciicode \endoflinecatcode % `\^^M ascii return is end-line
+\catcode\endoffileasciicode \ignorecatcode % `\^^Z endoffile (ignored in ConTeXt)
+%catcode\spaceasciicode \spacecatcode % `\ ascii space is blank space
+\catcode\hashasciicode \parametercatcode % `\# hash mark is macro parameter character
+\catcode\dollarasciicode \mathshiftcatcode % `\$ dollar sign is math shift
+%catcode\commentasciicode \commentcatcode % `\% percent sign is comment character
+\catcode\ampersandasciicode \alignmentcatcode % `\& ampersand is alignment tab
+%catcode\backslashasciicode \escapecatcode % `\\ backslash is TeX escape character
+\catcode\circumflexasciicode \superscriptcatcode % `\^ circumflex and uparrow are for superscripts
+\catcode\underscoreasciicode \subscriptcatcode % `\_ underline and downarrow are for subscripts
+\catcode\leftbraceasciicode \begingroupcatcode % `\{ left brace is begin-group character
+\catcode\rightbraceasciicode \endgroupcatcode % `\} right brace is end-group character
+\catcode\tildeasciicode \activecatcode % `\~ tilde is active
+%catcode\delasciicode \invalidcatcode % `\^^? ascii delete is invalid
+
+\chardef\statuswrite 128
%D Initialization of primitives.
-\directlua 0 { % this info is stored in the format
- lua.name[0] = "main ctx instance"
+\directlua {
+ local baseprimitives = tex.extraprimitives("core","tex")
+ local moreprimitives = tex.extraprimitives("etex","luatex")
- local coreprimitives = tex.extraprimitives("core")
- local texprimitives = tex.extraprimitives("tex")
- local etexprimitives = tex.extraprimitives("etex")
- local luatexprimitives = tex.extraprimitives("luatex")
+ tex.enableprimitives("",moreprimitives)
- tex.enableprimitives("",etexprimitives)
- tex.enableprimitives("",luatexprimitives)
+ tex.enableprimitives("normal",baseprimitives)
+ tex.enableprimitives("normal",moreprimitives)
- tex.enableprimitives("normal",coreprimitives)
- tex.enableprimitives("normal",texprimitives)
- tex.enableprimitives("normal",etexprimitives)
- tex.enableprimitives("normal",luatexprimitives)
+ function tex.enableprimitives() end
}
-%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:
+\def\space{ }
+\def\empty{}
+
+\letcharcode \formfeedasciicode \par % \def ^^L{\par} formfeed
+\letcharcode \tildeasciicode \ % tilde
+\letcharcode \spaceasciicode \space % space
-\def\gobbleoneargument#1{} % will be defined later on anyway
+\expandafter\def\csname\Uchar\tabasciicode \endcsname {\ } % \def\^^I{\ } tab
+\expandafter\def\csname\Uchar\formfeedasciicode \endcsname {\par} % \def\^^L{\par} formfeed
+\expandafter\def\csname\Uchar\endoflineasciicode\endcsname {\ } % \def\^^M{\ } return
-\mathchardef\etexversion = \numexpr\eTeXversion*100+\expandafter\gobbleoneargument\eTeXrevision\relax
+%D For now:
+
+\def\gobbleoneargument#1{} % will be defined later on anyway
%D First we define a simplified version of the \CONTEXT\ protection mechanism.
%D Later we will implement a better variant.
\def\unprotect
{\edef\protect
- {\catcode`@=\the\catcode`@\relax
- \catcode`?=\the\catcode`?\relax
- \catcode`!=\the\catcode`!\relax
- \catcode`_=\the\catcode`_\relax
+ {\catcode\atsignasciicode \the\catcode\atsignasciicode \relax
+ \catcode\exclamationmarkasciicode\the\catcode\exclamationmarkasciicode\relax
+ \catcode\questionmarkasciicode \the\catcode\questionmarkasciicode \relax
+ \catcode\underscoreasciicode \the\catcode\underscoreasciicode \relax
\let\protect\relax}%
- \catcode`@=11
- \catcode`?=11
- \catcode`!=11
- \catcode`_=11 }
+ \catcode\atsignasciicode \lettercatcode
+ \catcode\exclamationmarkasciicode\lettercatcode
+ \catcode\questionmarkasciicode \lettercatcode
+ \catcode\underscoreasciicode \lettercatcode}
\let\protect\relax
@@ -169,13 +177,13 @@
\countdef \c_syst_max_allocated_read = 55 \c_syst_max_allocated_read = 16
\countdef \c_syst_min_allocated_language = 56 \c_syst_min_allocated_language = 0
\countdef \c_syst_max_allocated_language = 57 \c_syst_max_allocated_language = 255
-\countdef \c_syst_max_allocated_insert = 58 \c_syst_max_allocated_insert = 254
-\countdef \c_syst_min_allocated_insert = 59 \c_syst_min_allocated_insert = 128
+\countdef \c_syst_min_allocated_insert = 58 \c_syst_min_allocated_insert = 128
+\countdef \c_syst_max_allocated_insert = 59 \c_syst_max_allocated_insert = 254
\countdef \c_syst_min_allocated_family = 60 \c_syst_min_allocated_family = 128
\countdef \c_syst_max_allocated_family = 61 \c_syst_max_allocated_family = 255
-\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 127-1023 : private
-\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0 % luatex >= 0.82
-\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 127 % luatex >= 0.82
+\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 0-1023 : private
+\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0
+\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 127
\countdef \c_syst_last_allocated_count = 32 \c_syst_last_allocated_count = \c_syst_min_allocated_register
\countdef \c_syst_last_allocated_dimen = 33 \c_syst_last_allocated_dimen = \c_syst_min_allocated_register
@@ -212,10 +220,10 @@
% A few traditional allocations (these might go):
-\countdef \count@ = 255 % hm, used in \newif .. todo: replace it there
-\dimendef \dimen@ = 0
-\dimendef \dimen@i = 1 % global only
-\dimendef \dimen@ii = 2
+\countdef \count@ 255 % hm, used in \newif .. todo: replace it there
+\dimendef \dimen@ 0
+\dimendef \dimen@i 1 % global only
+\dimendef \dimen@ii 2
%D So, effectively we start allocating from 256 and upwards. The inserts sit in the
%D range 128 upto 254. Page numbers use the counters 0 upto 9 and the pagebox is
@@ -258,8 +266,7 @@
% %D The next definitions are really needed (in \CONTEXT):
-%newlinechar=10 \def\outputnewlinechar{\rawcharacter{10}}
-\newlinechar=10 \edef\outputnewlinechar{^^J}
+\newlinechar\newlineasciicode \edef\outputnewlinechar{\Uchar\newlineasciicode} % {^^J}
%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
@@ -268,7 +275,8 @@
%D as all engines now provide many registers we removed all traces.
\ifdefined\writestatus \else
- \normalprotected\def\writestatus#1#2{\immediate\write\statuswrite{#1: #2}}
+ %\normalprotected\def\writestatus#1#2{\immediate\write\statuswrite{#1: #2}}
+ \normalprotected\def\writestatus#1#2{\message{#1: #2}}
\fi
\def\syst_basics_allocate_yes#1#2#3#4#5% last class method max name
@@ -304,6 +312,7 @@
%D 128-1023 are private and should not be touched.
\let\attributeunsetvalue\c_syst_min_counter_value % used to be \minusone
+
\normalprotected\def\newattribute{\syst_basics_allocate\c_syst_last_allocated_attribute\attribute\attributedef\c_syst_max_allocated_register}
%D Not used by \CONTEXT\ but for instance \PICTEX\ needs it. It's a trick to force
@@ -344,6 +353,10 @@
\newtoks \scratchtoksfour \newtoks \scratchtoksfive \newtoks \scratchtokssix
\newbox \scratchboxfour \newbox \scratchboxfive \newbox \scratchboxsix
+\newcount\globalscratchcounterone
+\newcount\globalscratchcountertwo
+\newcount\globalscratchcounterthree
+
%D \macros
%D {tempstring}
@@ -395,19 +408,19 @@
%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
-\newcount \maxcount \maxcount = 2147483647
-\newdimen \onebasepoint \onebasepoint = 1bp
-\newdimen \scaledpoint \scaledpoint = 1sp
-\newdimen \thousandpoint \thousandpoint = 1000pt
-\newmuskip\zeromuskip \zeromuskip = 0mu
-\newmuskip\onemuskip \onemuskip = 1mu
+\newskip \zeroskip \zeroskip 0pt plus 0pt minus 0pt
+\newdimen \zeropoint \zeropoint 0pt
+\newdimen \onepoint \onepoint 1pt
+\newdimen \halfapoint \halfapoint 0.5pt
+\newdimen \maxdimen \maxdimen 16383.99999pt
+\newcount \maxcount \maxcount 2147483647
+\newdimen \onebasepoint \onebasepoint 1bp
+\newdimen \scaledpoint \scaledpoint 1sp
+\newdimen \thousandpoint \thousandpoint 1000pt
+\newmuskip\zeromuskip \zeromuskip 0mu
+\newmuskip\onemuskip \onemuskip 1mu
-\newmuskip\muquad \muquad = 18mu
+\newmuskip\muquad \muquad 18mu
\let\points \onepoint
\let\halfpoint\halfapoint
@@ -416,32 +429,35 @@
%D And even more: (todo: countdefs 60+)
-%newcount \minusone \minusone = -1
-\newcount \minustwo \minustwo = -2
-%chardef \zerocount = 0
-%chardef \plusone = 1
-\chardef \plustwo = 2
-\chardef \plusthree = 3
-\chardef \plusfour = 4
-\chardef \plusfive = 5
-\chardef \plussix = 6
-\chardef \plusseven = 7
-\chardef \pluseight = 8
-\chardef \plusnine = 9
-\chardef \plusten = 10
-\chardef \plussixteen = 16
-\chardef \plushundred = 100
-\chardef \plustwohundred = 200
-\chardef \pluscxxvii = 127
-\chardef \pluscxxviii = 128
-\chardef \pluscclv = 255
-\chardef \pluscclvi = 256
-\chardef \plusthousand = 1000
-\chardef \plustenthousand = 10000
-\chardef \plustwentythousand = 20000
-\chardef \medcard = 32768
-\chardef \maxcard = 65536 % pdftex has less mathchars
-\chardef \maxcardminusone = 65535
+%newcount\minusone \minusone -1
+\newcount\minustwo \minustwo -2
+%chardef \zerocount 0
+%chardef \plusone 1
+\chardef \plustwo 2
+\chardef \plusthree 3
+\chardef \plusfour 4
+\chardef \plusfive 5
+\chardef \plussix 6
+\chardef \plusseven 7
+\chardef \pluseight 8
+\chardef \plusnine 9
+\chardef \plusten 10
+\chardef \plussixteen 16
+\chardef \plusfifty 50
+\chardef \plushundred 100
+\chardef \plusonehundred 100
+\chardef \plustwohundred 200
+\chardef \plusfivehundred 500
+\chardef \pluscxxvii 127
+\chardef \pluscxxviii 128
+\chardef \pluscclv 255
+\chardef \pluscclvi 256
+\chardef \plusthousand 1000
+\chardef \plustenthousand 10000
+\chardef \plustwentythousand 20000
+\chardef \medcard 32768
+\chardef \maxcard 65536 % pdftex has less mathchars
+\chardef \maxcardminusone 65535
%D \macros
%D {doubleexpandafter,tripleexpandafter,expanded,startexpanded}
@@ -462,8 +478,8 @@
\def\unvoidbox{\unhbox\voidbox}
\def\emptybox {\box \voidbox} % used in initializations so no attributes
-\def\emptyvbox{\normalvbox{}} % no copy as we need to set attributes
-\def\emptyhbox{\normalhbox{}} % no copy as we need to set attributes
+\def\emptyvbox{\normalvpack{}} % no copy as we need to set attributes
+\def\emptyhbox{\normalhpack{}} % no copy as we need to set attributes
\let\leavevmode\unvoidbox % we prefer to use \dontleavehmode
@@ -506,21 +522,47 @@
%D creates \type {\footrue}, \type {\foofalse} to go with \type {\iffoo}.
%D \stopnarrower
-\normalprotected\def\newif#1%
- {\count@\escapechar
- \escapechar\minusone
- \expandafter\expandafter\expandafter\def\@if #1{true}{\let#1\iftrue }%
- \expandafter\expandafter\expandafter\def\@if#1{false}{\let#1\iffalse}%
- \@if#1{false}% the condition starts out false
- \escapechar\count@}
-
-\def\@if#1#2%
- {\csname\expandafter\if@\string#1#2\endcsname}
+% \normalprotected\def\newif#1%
+% {\count@\escapechar
+% \escapechar\minusone
+% \expandafter\expandafter\expandafter\def\new_if #1{true}{\let#1\iftrue }%
+% \expandafter\expandafter\expandafter\def\new_if#1{false}{\let#1\iffalse}%
+% \new_if#1{false}% the condition starts out false
+% \escapechar\count@}
+%
+% \def\new_if#1#2%
+% {\csname\expandafter\if@\string#1#2\endcsname}
+%
+% \bgroup % `if' is required
+% \uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}}
+% \egroup
-\bgroup % `if' is required
+% We use \csstring so there is no need to push/pop escapechar.
+% We use different names so that we get a better error message.
+%
+% \normalprotected\def\newif#1%
+% {\let\new_if_saved\newif
+% \let\newif\new_if_check
+% \expandafter\expandafter\expandafter\def\new_if_cs #1{true}{\let#1\iftrue }%
+% \expandafter\expandafter\expandafter\def\new_if_cs#1{false}{\let#1\iffalse}%
+% \new_if_cs#1{false}%
+% \let\newif\new_if_saved}
+%
+% \normalprotected\def\new_if_cs#1#2%
+% {\csname\expandafter\newif\csstring#1#2\endcsname}
+%
+% We wrap all into one macro:
- \uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}}
+\normalprotected\def\newif#1%
+ {\let\new_if_saved\newif
+ \let\newif\new_if_check
+ \expandafter\def\csname\expandafter\newif\csstring#1true\endcsname {\let#1\iftrue }%
+ \expandafter\def\csname\expandafter\newif\csstring#1false\endcsname{\let#1\iffalse}%
+ \csname\expandafter\newif\csstring#1false\endcsname
+ \let\newif\new_if_saved}
+\bgroup
+ \normalexpanded{\gdef\noexpand\new_if_check\string i\string f{}}
\egroup
%D Let's test this one:
@@ -534,32 +576,11 @@
%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
-\chardef\endgroupcatcode = 2
-\chardef\mathshiftcatcode = 3
-\chardef\alignmentcatcode = 4
-\chardef\endoflinecatcode = 5
-\chardef\parametercatcode = 6
-\chardef\superscriptcatcode = 7
-\chardef\subscriptcatcode = 8
-\chardef\ignorecatcode = 9
-\chardef\spacecatcode = 10
-\chardef\lettercatcode = 11
-\chardef\othercatcode = 12
-\chardef\activecatcode = 13
-\chardef\commentcatcode = 14
-\chardef\invalidcatcode = 15
-
%D For a while we keep the following, as systems like tikz need it. Best
%D not use that one \CONTEXT.
@@ -789,7 +810,8 @@
\normalprotected\def\newmacro #1{\let#1\empty}
\normalprotected\def\setnewmacro#1{\let#1}
-\def\!!plusone{1}
+\def\!!zerocount{0}
+\def\!!plusone {1}
\normalprotected\def\newfraction#1{\let#1\!!plusone}
@@ -872,28 +894,28 @@
\let\endgraf\par
\let\endline\cr
-\def\space{ }
-\def\empty{}
-
\normalprotected\def\null{\hpack{}}
%D The following two might be overloaded later on but some modules need then
%D earlier. These functionality is reflected in the name and will not change.
-\bgroup
- \catcode`\^^M=\activecatcode%
- \gdef\obeylines{\catcode`\^^M\activecatcode \let^^M\par}%
- \global\let^^M\par%
-\egroup
-
-\bgroup
- \gdef\obeyspaces{\catcode`\ \activecatcode}%
- \obeyspaces\global\let =\space%
-\egroup
+% \bgroup
+% \catcode`\^^M=\activecatcode%
+% \gdef\obeylines{\catcode`\^^M\activecatcode \let^^M\par}%
+% \glet^^M\par%
+% \egroup
+%
+% \bgroup
+% \gdef\obeyspaces{\catcode`\ \activecatcode}%
+% \obeyspaces\glet =\space%
+% \egroup
-%D A constant:
+\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\par}
+\def\obeyspaces{\catcode\spaceasciicode \activecatcode\letcharcode\spaceasciicode \space}
-\let\endoflinetoken=^^M
+% %D A constant:
+%
+% \let\endoflinetoken=^^M
%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
@@ -948,6 +970,12 @@
\lineskip = 1pt
\lineskiplimit = 0pt
+%D Sometimes kerns make more sense than glue but we need to be in the
+%D right mode:
+
+\normalprotected\def\vkern{\ifhmode\par \fi\kern}
+\normalprotected\def\hkern{\ifvmode\dontleavehmode\fi\kern}
+
%D Again a few kind-of-extensions the core. These come from plain \TEX\ but
%D are probably not used in \CONTEXT.
@@ -976,116 +1004,47 @@
%D Backend:
-% For the moment we define some \pdf... helpers but this will move to the backend
-% module after which the official interfaces have to be used. This is needed for
-% modules not made by ctx developers.
-
-\normalprotected\def\pdfliteral {\pdfextension literal }
-\normalprotected\def\pdfcolorstack {\pdfextension colorstack }
-\normalprotected\def\pdfsetmatrix {\pdfextension setmatrix }
-\normalprotected\def\pdfsave {\pdfextension save\relax}
-\normalprotected\def\pdfrestore {\pdfextension restore\relax}
-\normalprotected\def\pdfobj {\pdfextension obj }
-\normalprotected\def\pdfrefobj {\pdfextension refobj }
-\normalprotected\def\pdfannot {\pdfextension annot }
-\normalprotected\def\pdfstartlink {\pdfextension startlink }
-\normalprotected\def\pdfendlink {\pdfextension endlink\relax}
-\normalprotected\def\pdfoutline {\pdfextension outline }
-\normalprotected\def\pdfdest {\pdfextension dest }
-\normalprotected\def\pdfthread {\pdfextension thread }
-\normalprotected\def\pdfstartthread {\pdfextension startthread }
-\normalprotected\def\pdfendthread {\pdfextension endthread\relax}
-\normalprotected\def\pdfinfo {\pdfextension info }
-\normalprotected\def\pdfcatalog {\pdfextension catalog }
-\normalprotected\def\pdfnames {\pdfextension names }
-\normalprotected\def\pdfincludechars {\pdfextension includechars }
-\normalprotected\def\pdffontattr {\pdfextension fontattr }
-\normalprotected\def\pdfmapfile {\pdfextension mapfile }
-\normalprotected\def\pdfmapline {\pdfextension mapline }
-\normalprotected\def\pdftrailer {\pdfextension trailer }
-\normalprotected\def\pdfglyphtounicode {\pdfextension glyphtounicode }
-
-% \chardef\pdfnofullbanner = 1
-% \chardef\pdfnofilename = 2
-% \chardef\pdfnopagenumber = 4
-% \chardef\pdfnoinfodict = 8
-% \chardef\pdfnocreator = 16
-% \chardef\pdfnocreationdate = 32
-% \chardef\pdfnomoddate = 64
-% \chardef\pdfnoproducer = 128
-% \chardef\pdfnotrapped = 256
-% \chardef\pdfnoid = 512
-
-\def\pdftexversion {\numexpr\pdffeedback version\relax}
-\def\pdftexrevision {\pdffeedback revision}
-\def\pdflastlink {\numexpr\pdffeedback lastlink\relax}
-\def\pdfretval {\numexpr\pdffeedback retval\relax}
-\def\pdflastobj {\numexpr\pdffeedback lastobj\relax}
-\def\pdflastannot {\numexpr\pdffeedback lastannot\relax}
-\def\pdfxformname {\numexpr\pdffeedback xformname\relax}
-\def\pdfcreationdate {\pdffeedback creationdate}
-\def\pdffontname {\numexpr\pdffeedback fontname\relax}
-\def\pdffontobjnum {\numexpr\pdffeedback fontobjnum\relax}
-\def\pdffontsize {\dimexpr\pdffeedback fontsize\relax}
-\def\pdfpageref {\numexpr\pdffeedback pageref\relax}
-\def\pdfcolorstackinit {\pdffeedback colorstackinit}
-
-\let\pdfxform \saveboxresource
-\let\pdflastxform \lastsavedboxresourceindex
-\let\pdfrefxform \useboxresource
-\let\pdfximage \saveimageresource
-\let\pdflastximage \lastsavedimageresourceindex
-\let\pdflastximagepages \lastsavedimageresourcepages
-\let\pdfrefximage \useimageresource
-\let\pdfsavepos \savepos
-\let\pdflastxpos \lastxpos
-\let\pdflastypos \lastypos
-
-\edef\pdfcompresslevel {\pdfvariable compresslevel} \pdfcompresslevel \plusnine
-\edef\pdfobjcompresslevel {\pdfvariable objcompresslevel} \pdfobjcompresslevel \plusone
-\edef\pdfdecimaldigits {\pdfvariable decimaldigits} \pdfdecimaldigits \plusfive
-\edef\pdfgamma {\pdfvariable gamma} \pdfgamma \plusthousand
-\edef\pdfimageresolution {\pdfvariable imageresolution} \pdfimageresolution 300
-\edef\pdfimageapplygamma {\pdfvariable imageapplygamma} \pdfimageapplygamma \zerocount
-\edef\pdfimagegamma {\pdfvariable imagegamma} \pdfimagegamma 2200
-\edef\pdfimagehicolor {\pdfvariable imagehicolor} \pdfimagehicolor \plusone
-\edef\pdfimageaddfilename {\pdfvariable imageaddfilename} \pdfimageaddfilename \plusone
-\edef\pdfpkresolution {\pdfvariable pkresolution} \pdfpkresolution 1200
-\edef\pdfinclusioncopyfonts {\pdfvariable inclusioncopyfonts} \pdfinclusioncopyfonts \plusone
-\edef\pdfinclusionerrorlevel {\pdfvariable inclusionerrorlevel} \pdfinclusionerrorlevel \zerocount
-\edef\pdfgentounicode {\pdfvariable gentounicode} \pdfgentounicode \plusone
-\edef\pdfpagebox {\pdfvariable pagebox} \pdfpagebox \zerocount
-\edef\pdfmajorversion {\pdfvariable majorversion} % \pdfmajorversion \plusone
-\edef\pdfminorversion {\pdfvariable minorversion} \pdfminorversion \plusseven
-\edef\pdfuniqueresname {\pdfvariable uniqueresname} \pdfuniqueresname \zerocount
-\edef\pdfhorigin {\pdfvariable horigin} \pdfhorigin 1in
-\edef\pdfvorigin {\pdfvariable vorigin} \pdfvorigin \pdfhorigin
-\edef\pdflinkmargin {\pdfvariable linkmargin} \pdflinkmargin \zeropoint
-\edef\pdfdestmargin {\pdfvariable destmargin} \pdfdestmargin \zeropoint
-\edef\pdfthreadmargin {\pdfvariable threadmargin} \pdfthreadmargin \zeropoint
-\edef\pdfxformmargin {\pdfvariable xformmargin} \pdfxformmargin \zeropoint
-\edef\pdfpkfixeddpi {\pdfvariable pkfixeddpi} \pdfpkfixeddpi \plusone
-\edef\pdfignoreunknownimages {\pdfvariable ignoreunknownimages} \pdfignoreunknownimages \zerocount
-
-\edef\pdfpagesattr {\pdfvariable pagesattr}
-\edef\pdfpageattr {\pdfvariable pageattr}
-\edef\pdfpageresources {\pdfvariable pageresources}
-\edef\pdfxformattr {\pdfvariable xformattr}
-\edef\pdfxformresources {\pdfvariable xformresources}
-\edef\pdfpkmode {\pdfvariable pkmode}
-
-\edef\pdfsuppressoptionalinfo{\pdfvariable suppressoptionalinfo }
-\let \pdfsuppressptexinfo \pdfsuppressoptionalinfo
-\edef\pdftrailerid {\pdfvariable trailerid }
-\edef\pdfinfoomitdate {\pdfvariable suppressoptionalinfo \numexpr32+64\relax}
-
-\normalprotected\def\nopdfcompression {\pdfobjcompresslevel\zerocount \pdfcompresslevel\zerocount}
-\normalprotected\def\maximumpdfcompression{\pdfobjcompresslevel\plusnine \pdfcompresslevel\plusnine }
-\normalprotected\def\normalpdfcompression {\pdfobjcompresslevel\plusthree \pdfcompresslevel\plusthree}
-
-\normalpdfcompression
-
-\outputmode \zerocount % we generate the format in this mode
+\ifdefined\pdfvariable
+
+ \pdfvariable compresslevel \plusthree
+ \pdfvariable objcompresslevel \plusone
+ % \pdfvariable recompress \zerocount
+ \pdfvariable decimaldigits \plussix
+ \pdfvariable gamma \plusthousand
+ \pdfvariable imageresolution 300
+ \pdfvariable imageapplygamma \zerocount
+ \pdfvariable imagegamma 2200
+ \pdfvariable imagehicolor \plusone
+ \pdfvariable imageaddfilename \plusone
+ \pdfvariable pkresolution 1200
+ \pdfvariable inclusioncopyfonts \plusone
+ \pdfvariable inclusionerrorlevel \zerocount
+ \pdfvariable gentounicode \plusone
+ \pdfvariable omitcidset \plusone
+ \pdfvariable omitcharset \plusone
+ \pdfvariable pagebox \zerocount
+ % \pdfvariable majorversion % \plusone
+ \pdfvariable minorversion \plusseven
+ \pdfvariable uniqueresname \zerocount
+ \pdfvariable horigin 1in
+ \pdfvariable vorigin 1in
+ % \pdfvariable linkmargin \zeropoint
+ % \pdfvariable destmargin \zeropoint
+ % \pdfvariable threadmargin \zeropoint
+ % \pdfvariable xformmargin \zeropoint
+ \pdfvariable pkfixeddpi \plusone
+ \pdfvariable ignoreunknownimages \zerocount
+
+\fi
+
+\let\nopdfcompression \relax
+\let\onlypdfobjectcompression\relax
+\let\maximumpdfcompression \relax
+\let\normalpdfcompression \relax
+
+\ifdefined\outputmode
+ \outputmode \zerocount % we generate the format in this mode
+\fi
%D Basic status stuff.
@@ -1102,12 +1061,10 @@
\def\dividenumber#1#2{\the\numexpr(#2-(#1/2))/#1\relax}
\ifdefined\texenginename \else
- %edef\texenginename{luatex}
\edef\texenginename{\directlua{tex.print(LUATEXENGINE)}}
\fi
\ifdefined\texengineversion \else
- %edef\texengineversion{\dividenumber{100}\luatexversion.\modulonumber{100}\luatexversion.\luatexrevision}
\edef\texengineversion{\directlua{tex.print(LUATEXVERSION)}}
\fi
@@ -1120,43 +1077,39 @@
\savingvdiscards\plusone
%D We only can set this one via directives (system.synctex) and we only support
-%D the context variant.
+%D the context variant. This will go away completely.
\let\synctex\undefined \newcount\synctex \let\normalsynctex\synctex
%D We get rid of the funny \TEX\ offset defaults of one inch by setting them to zero.
-\voffset\zeropoint \let\voffset\relax \newdimen\voffset % prevent messing up
-\hoffset\zeropoint \let\hoffset\relax \newdimen\hoffset % prevent messing up
+\voffset\zeropoint \let\voffset\relax \newdimen\voffset \let\normalvoffset\voffset
+\hoffset\zeropoint \let\hoffset\relax \newdimen\hoffset \let\normalhoffset\hoffset
+
+\ifdefined\pageleftoffset
+ \let\pageleftoffset \hoffset \let\normalpageleftoffset \hoffset
+ \let\pagerightoffset \hoffset \let\normalpagerightoffset \hoffset
+ \let\pagetopoffset \voffset \let\normalpagetopoffset \voffset
+ \let\pagebottomoffset\voffset \let\normalpagebottomoffset\voffset
+\fi
%D Handy.
-\suppresslongerror \plusone % \let\suppresslongerror \relax
-\suppressoutererror \plusone % \let\suppressoutererror \relax
-\suppressmathparerror \plusone % \let\suppressmathparerror \relax
-\suppressifcsnameerror\plusone % \let\suppressifcsnameerror\relax
+\suppresslongerror \plusone
+\suppressoutererror \plusone
+\suppressmathparerror \plusone
+\suppressifcsnameerror\plusone
-\matheqnogapstep \zerocount % fr now
+\let \suppresslongerror \relax
+\newcount\suppresslongerror \let\normalsuppresslongerror \suppresslongerror
+\let \suppressoutererror \suppresslongerror \let\normalsuppressoutererror \suppresslongerror
+\let \suppressmathparerror \suppresslongerror \let\normalsuppressmathparerror \suppresslongerror
+\let \suppressifcsnameerror\suppresslongerror \let\normalsuppressifcsnameerror\suppresslongerror
-%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
-%D Given time I know that I can prove
-%D Now my world is opened up to you
-%D Come inside
-%D
-%D Welcome to my life
-%D Welcome to my world
-%D Come inside
-%D \stoplines
-%D
-%D So let's see what \TEX\ can do now that we've opened up the basic machinery.
+\matheqnogapstep\zerocount % for now
-%D Now we define a few helpers that we need in a very early stage. We hav eno message system
-%D yet but redundant definitions are fatal anyway.
+%D Now we define a few helpers that we need in a very early stage. We have no
+%D message system yet but redundant definitions are fatal anyway.
\newcount\c_syst_helpers_n_of_namespaces \c_syst_helpers_n_of_namespaces\pluseight % 1-8 reserved for catcodes
@@ -1183,30 +1136,4 @@
\let\normalstartdmath \Ustartdisplaymath
\let\normalstopdmath \Ustopdisplaymath
-%D For now:
-
-\ifdefined\protrusionboundary \else \let\protrusionboundary\boundary \fi
-\ifdefined\wordboundary \else \let\wordboundary \noboundary \fi
-
-\ifdefined\mathrulesfam \else \newcount\mathrulesfam \fi
-\ifdefined\mathrulesmode \else \newcount\mathrulesmode \fi
-\ifdefined\mathsurroundmode \else \newcount\mathsurroundmode \fi
-\ifdefined\mathitalicsmode \else \newcount\mathitalicsmode \fi
-\ifdefined\mathdelimitersmode \else \newcount\mathdelimitersmode \fi
-\ifdefined\mathscriptboxmode \else \newcount\mathscriptboxmode \fi
-
-\ifdefined\hyphenpenaltymode \else \newcount\hyphenpenaltymode \fi
-\ifdefined\automatichyphenpenalty \else \newcount\automatichyphenpenalty \fi
-\ifdefined\automatichyphenmode \else \newcount\automatichyphenmode \fi
-\ifdefined\explicithyphenpenalty \else \newcount\explicithyphenpenalty \fi
-
-\ifdefined\explicitdiscretionary \else \let\explicitdiscretionary \- \fi
-\ifdefined\automaticdiscretionary \else \def\automaticdiscretionary{\Uchar\exhyphenchar} \fi
-
-\ifdefined\mathpenaltiesmode \else \newcount\mathpenaltiesmode \fi
-\ifdefined\prebinoppenalty \else \newcount\prebinoppenalty \fi
-\ifdefined\prerelpenalty \else \newcount\prerelpenalty \fi
-
-\ifdefined\breakafterdirmode \else \newcount\breakafterdirmode \fi
-
\protect \endinput
diff --git a/tex/context/base/mkiv/syst-lua.lua b/tex/context/base/mkiv/syst-lua.lua
index 35cd22123..a63c49e8f 100644
--- a/tex/context/base/mkiv/syst-lua.lua
+++ b/tex/context/base/mkiv/syst-lua.lua
@@ -15,10 +15,10 @@ local context = context
local implement = interfaces.implement
local ctx_protected_cs = context.protected.cs -- more efficient
-local ctx_firstoftwoarguments = ctx_protected_cs.firstoftwoarguments
-local ctx_secondoftwoarguments = ctx_protected_cs.secondoftwoarguments
-local ctx_firstofoneargument = ctx_protected_cs.firstofoneargument
-local ctx_gobbleoneargument = ctx_protected_cs.gobbleoneargument
+local ctx_firstoftwoarguments = context.firstoftwoarguments
+local ctx_secondoftwoarguments = context.secondoftwoarguments
+local ctx_firstofoneargument = context.firstofoneargument
+local ctx_gobbleoneargument = context.gobbleoneargument
local two_strings = interfaces.strings[2]
@@ -105,7 +105,8 @@ local p_first = C((1-P(",")-P(-1))^0)
implement {
name = "firstinset",
arguments = "string",
- actions = function(str) context(lpegmatch(p_first,str or "")) end
+ actions = function(str) context(lpegmatch(p_first,str or "")) end,
+ public = true,
}
implement {
diff --git a/tex/context/base/mkiv/syst-lua.mkiv b/tex/context/base/mkiv/syst-lua.mkiv
index ca5f9679f..3600dac34 100644
--- a/tex/context/base/mkiv/syst-lua.mkiv
+++ b/tex/context/base/mkiv/syst-lua.mkiv
@@ -19,6 +19,42 @@
\def\expdoif #1#2{\clf_doifsame {#1}{#2}}
\def\expdoifnot #1#2{\clf_doifnotsame {#1}{#2}}
+%D Here is variant using a brainwave of the 12\high{+} hour \quotation {Long Road
+%D Out of Eden}\footnote {Eden being Backo\TeX\ 2018, where the virtues of the \type
+%D {\expanded} primitive were mentioned in talks.} trip. For now I don't really see
+%D other useful applications.
+
+\ifdefined\immediateassignment
+
+ \def\expandeddoif#1#2%
+ {\immediateassignment\edef\m_syst_string_one{#1}%
+ \immediateassignment\edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+ \def\expandeddoifnot#1#2%
+ {\immediateassignment\edef\m_syst_string_one{#1}%
+ \immediateassignment\edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+ \def\expandeddoifelse#1#2%
+ {\immediateassignment\edef\m_syst_string_one{#1}%
+ \immediateassignment\edef\m_syst_string_two{#2}%
+ \ifx\m_syst_string_one\m_syst_string_two
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\fi
+
% \testfeatureonce{100000}{\doifelse{hello world}{here i am}{}} % 0.3
% \testfeatureonce{100000}{\expandabledoifelse{hello world}{here i am}{}} % 1.5
diff --git a/tex/context/base/mkii/syst-rtp.mkiv b/tex/context/base/mkiv/syst-rtp.mkiv
index 82c0778b4..82c0778b4 100644
--- a/tex/context/base/mkii/syst-rtp.mkiv
+++ b/tex/context/base/mkiv/syst-rtp.mkiv
diff --git a/tex/context/base/mkiv/tabl-com.mkiv b/tex/context/base/mkiv/tabl-com.mkiv
index e90086368..01a55e313 100644
--- a/tex/context/base/mkiv/tabl-com.mkiv
+++ b/tex/context/base/mkiv/tabl-com.mkiv
@@ -15,39 +15,51 @@
\unprotect
-\let\VL\relax
-
-\let\NC\relax
-\let\RC\relax
-\let\HC\relax
-\let\EQ\relax
-
-\let\RQ\relax
-\let\HQ\relax
-
-\let\NG\relax
-\let\NN\relax
-\let\ND\relax
-\let\NR\relax
-\let\NB\relax
-
+\let\AR\relax
+\let\BA\relax
+\let\BC\relax
+\let\BL\relax
\let\CC\relax
\let\CL\relax
\let\CM\relax
\let\CR\relax
-
-\let\SR\relax
+\let\DB\relax
+\let\EQ\relax
+\let\FB\relax
+\let\FL\relax
\let\FR\relax
-\let\MR\relax
+\let\HC\relax
+\let\HL\relax
+\let\HQ\relax
+\let\HR\relax
+\let\LB\relax
+\let\LL\relax
\let\LR\relax
-\let\AR\relax
-
-\let\FL\relax
\let\ML\relax
-\let\LL\relax
+\let\MR\relax
+\let\NA\relax
+\let\NB\relax
+\let\NC\relax
+\let\ND\relax
+\let\NF\relax
+\let\NG\relax
+\let\NI\relax
+\let\NL\relax
+\let\NN\relax
+\let\NP\relax
+\let\NR\relax
+\let\PB\relax
+\let\RC\relax
+\let\RQ\relax
+\let\SR\relax
\let\TL\relax
-\let\BL\relax
-\let\HL\relax
-\let\HR\relax
+\let\VL\relax
+
+\installmacrostack\BC
+\installmacrostack\EC
+\installmacrostack\EQ
+\installmacrostack\NC
+\installmacrostack\NN
+\installmacrostack\NR
\protect \endinput
diff --git a/tex/context/base/mkiv/tabl-ltb.mkiv b/tex/context/base/mkiv/tabl-ltb.mkiv
index 3147fa1cc..20ae8bf5a 100644
--- a/tex/context/base/mkiv/tabl-ltb.mkiv
+++ b/tex/context/base/mkiv/tabl-ltb.mkiv
@@ -705,14 +705,14 @@
\else
\t_tabl_lines_head\emptytoks
\fi
- \pushmacro\BC
- \pushmacro\EC
+ \push_macro_BC
+ \push_macro_EC
\def\BC##1\EC{\appendtoks##1\to\t_tabl_lines_head}%
\let\EC\relax} % signal
\unexpanded\def\tabl_lines_EH
- {\popmacro\EC
- \popmacro\BC
+ {\pop_macro_EC
+ \pop_macro_BC
\expandafter\startlinetablehead\the\t_tabl_lines_head\stoplinetablehead}
\let\startlinetablebody\relax
diff --git a/tex/context/base/mkiv/tabl-ntb.mkiv b/tex/context/base/mkiv/tabl-ntb.mkiv
index 9acf2ef36..ca3d78800 100644
--- a/tex/context/base/mkiv/tabl-ntb.mkiv
+++ b/tex/context/base/mkiv/tabl-ntb.mkiv
@@ -271,10 +271,10 @@
\letvalue{\??naturaltablesqueeze\v!broad}\donetrue
\letvalue{\??naturaltablesqueeze\v!local}\donetrue
-\def\tabl_ntb_let_gal{\global\expandafter\let\csname\??naturaltablegal\m_tabl_tbl_level\endcsname}
+\def\tabl_ntb_let_gal{\expandafter\glet\csname\??naturaltablegal\m_tabl_tbl_level\endcsname}
\def\tabl_ntb_get_gal{\csname\??naturaltablegal\m_tabl_tbl_level\endcsname}
-\def\tabl_ntb_let_tal#1{\global\expandafter\let\csname\??naturaltabletal\m_tabl_tbl_level:\number#1\endcsname}
+\def\tabl_ntb_let_tal#1{\expandafter\glet\csname\??naturaltabletal\m_tabl_tbl_level:\number#1\endcsname}
\def\tabl_ntb_get_tal#1{\csname\??naturaltabletal\m_tabl_tbl_level:\number#1\endcsname}
\def\tabl_ntb_set_nob#1{\expandafter\let\csname\??naturaltablenob\m_tabl_tbl_level:\number#1\endcsname\plusone}
@@ -291,8 +291,8 @@
%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_let_wd#1#2{\expandafter\glet\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global !
+\def\tabl_ntb_let_ht#1#2{\expandafter\glet\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}
@@ -306,10 +306,10 @@
\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_let_wid#1{\expandafter\glet\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_let_hei#1{\expandafter\glet\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_let_dis#1{\expandafter\glet\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global !
+\def\tabl_ntb_let_aut#1{\expandafter\glet\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\lastnamedcs\else\zeropoint\fi}
\def\tabl_ntb_get_hei#1{\ifcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
@@ -1161,13 +1161,11 @@
\def\tabl_ntb_row_stop_boxed
{% \noindent % no, else double leftskip in narrower
- \normalexpanded
- {\t_tabl_ntb
- {\the\t_tabl_ntb
- % no need for init
- \tabl_ntb_row_align_start
- \the\t_tabl_ntb_row
- \tabl_ntb_row_align_stop}}}
+ \etoksapp\t_tabl_ntb
+ {% no need for init
+ \tabl_ntb_row_align_start
+ \the\t_tabl_ntb_row
+ \tabl_ntb_row_align_stop}}
\def\tabl_ntb_row_stop_split
{\ifcsname\??naturaltableset\m_tabl_tbl_level:\c!y++\the\c_tabl_ntb_current_row\endcsname
@@ -1177,13 +1175,11 @@
\fi}
\def\tabl_ntb_row_stop_split_nop
- {\normalexpanded
- {\t_tabl_ntb
- {\the\t_tabl_ntb
- \tabl_ntb_row_align_reset
- \tabl_ntb_row_align_start
- \the\t_tabl_ntb_row
- \tabl_ntb_row_align_stop}}}
+ {\etoksapp\t_tabl_ntb
+ {\tabl_ntb_row_align_reset
+ \tabl_ntb_row_align_start
+ \the\t_tabl_ntb_row
+ \tabl_ntb_row_align_stop}}
\def\tabl_ntb_row_stop_split_yes
{\begingroup
@@ -1192,13 +1188,11 @@
\xdef\m_tabl_ntb_after_split {\naturaltablelocalparameter\c!after}% to be checked
\xdef\m_tabl_ntb_same_page {\naturaltablelocalparameter\c!samepage}%
\endgroup
- \normalexpanded
- {\t_tabl_ntb
- {\the\t_tabl_ntb
- \tabl_ntb_row_align_set{\m_tabl_ntb_before_split}{\m_tabl_ntb_after_split}{\m_tabl_ntb_same_page}%
- \tabl_ntb_row_align_start
- \the\t_tabl_ntb_row
- \tabl_ntb_row_align_stop}}}
+ \etoksapp\t_tabl_ntb
+ {\tabl_ntb_row_align_set{\m_tabl_ntb_before_split}{\m_tabl_ntb_after_split}{\m_tabl_ntb_same_page}%
+ \tabl_ntb_row_align_start
+ \the\t_tabl_ntb_row
+ \tabl_ntb_row_align_stop}}
\unexpanded\def\tabl_ntb_row_align_set#1#2#3%
{\xdef\m_tabl_ntb_before_split{#1}%
@@ -1206,9 +1200,9 @@
\xdef\m_tabl_ntb_same_page {#3}}
\unexpanded\def\tabl_ntb_row_align_reset
- {\global\let\m_tabl_ntb_before_split\empty
- \global\let\m_tabl_ntb_after_split \empty
- \global\let\m_tabl_ntb_same_page \empty}
+ {\glet\m_tabl_ntb_before_split\empty
+ \glet\m_tabl_ntb_after_split \empty
+ \glet\m_tabl_ntb_same_page \empty}
\def\tabl_ntb_prelocate_error
{\writestatus\m!TABLE{fatal error: use \string\prelocateTBLrows\space to increase table memory (now: \the\c_tabl_prelocated_rows)}}
@@ -1225,12 +1219,10 @@
\tabl_ntb_prelocate_error
\fi}%
\def\tabl_ntb_row_stop
- {\normalexpanded
- {\t_tabl_ntb
- {\the\t_tabl_ntb
- \tabl_ntb_row_align_start
- \the\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname
- \tabl_ntb_row_align_stop}}}%
+ {\etoksapp\t_tabl_ntb
+ {\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}
\def\tabl_ntb_prelocate_okay
@@ -1344,37 +1336,23 @@
{\global\advance\c_tabl_ntb_col\plusone
\kern\d_tabl_ntb_columndistance}
-% \setvalue{\??naturaltablecell\the\c_tabl_ntb_none}#1#2%
-% {\scratchcounter\tabl_ntb_get_col{#1}{#2}\relax
-% \ifnum\scratchcounter>\zerocount
-% \normalexpanded
-% {\t_tabl_ntb_row
-% {\the\t_tabl_ntb_row
-% \tabl_ntb_span{\the\scratchcounter}%
-% \tabl_ntb_plus}}%
-% \fi}
-
\setvalue{\??naturaltablecell\the\c_tabl_ntb_none}#1#2%
{\scratchcounter\tabl_ntb_get_col{#1}{#2}\relax
\ifnum\scratchcounter>\zerocount
- \normalexpanded
- {\t_tabl_ntb_row
- {\the\t_tabl_ntb_row
- \tabl_ntb_span{\the\scratchcounter}}}%
+ \etoksapp\t_tabl_ntb_row
+ {\tabl_ntb_span{\the\scratchcounter}}%
\fi}
\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
+ {\toksapp\t_tabl_ntb_row{\tabl_ntb_pass #1 #2 }% space delimited -> less tokens
\scratchcounter\tabl_ntb_get_col{#1}{#2}\relax
\ifnum\scratchcounter>\zerocount
- \normalexpanded
- {\t_tabl_ntb_row
- {\the\t_tabl_ntb_row
- \ifnum\scratchcounter=\plusone
- \tabl_ntb_plus
- \else
- \tabl_ntb_skip{\the\scratchcounter}%
- \fi}}%
+ \etoksapp\t_tabl_ntb_row
+ {\ifnum\scratchcounter=\plusone
+ \tabl_ntb_plus
+ \else
+ \tabl_ntb_skip{\the\scratchcounter}%
+ \fi}%
\fi}
\unexpanded\def\tabl_ntb_cell#1#2%
diff --git a/tex/context/base/mkiv/tabl-tab.mkiv b/tex/context/base/mkiv/tabl-tab.mkiv
index 54b18a385..631f29bc0 100644
--- a/tex/context/base/mkiv/tabl-tab.mkiv
+++ b/tex/context/base/mkiv/tabl-tab.mkiv
@@ -417,7 +417,7 @@
% Key "a": a{TOKENS} adds TOKENS to the right of (after) the template
\newtableformatkey a#1%
- {\!taDataColumnTemplate\expandafter{\the\!taDataColumnTemplate #1}%
+ {\toksapp\!taDataColumnTemplate{#1}%
\doreadtableformatkeys}
% Key "\{": Enclose template in braces.
@@ -435,7 +435,7 @@
\scratchtoks\emptytoks
\!thLoop
\ifnum\scratchcounter>\zerocount
- \scratchtoks\expandafter{\the\scratchtoks#2}%
+ \toksapp\scratchtoks{#2}%
\advance\scratchcounter\minusone
\repeat
\expandafter\doreadtableformatkeys\the\scratchtoks}
@@ -688,7 +688,7 @@
% extensions
\newtableformatkey q%
- {\letempty\!tqStyle
+ {\let\!tqStyle\empty
\futurelet\!tnext\!tqTestForBracket}
\newtableformatkey Q%
@@ -928,7 +928,7 @@
\global\c_tabl_table_n_of_vrules\plusone
\unskip
\fi
- \global\let\m_tabl_table_vrule_color\empty
+ \glet\m_tabl_table_vrule_color\empty
\hfil
\aligntab}
@@ -1370,8 +1370,8 @@
{\tabl_tables_chuck_auto_row % before the tail, else noalign problem
\tabl_table_insert_tail
\starttablenoalign
- \global\let\tabl_table_head\empty
- \global\let\tabl_table_tail\empty
+ \glet\tabl_table_head\empty
+ \glet\tabl_table_tail\empty
\stoptablenoalign
\tabl_table_finish
\ifx\p_tabl_table_frame\empty
@@ -1481,7 +1481,7 @@
\tabl_table_restart
% \starttablenoalign
% \globalpushmacro\simpletableHL
-% \global\let\simpletableHL\doverysimpletableHL
+% \glet\simpletableHL\doverysimpletableHL
% \stoptablenoalign
\tabl_table_insert_head
\ifsplittables \ifconditional \c_tabl_table_repeat_tail
@@ -1593,8 +1593,8 @@
\egroup
\dontcomplain
\tabl_table_split_box\tablecontentbox
- \global\let\tabl_table_head\empty % new here
- \global\let\tabl_table_tail\empty % new here
+ \glet\tabl_table_head\empty % new here
+ \glet\tabl_table_tail\empty % new here
\flushnotes
\egroup}
@@ -1691,8 +1691,8 @@
\starttablenoalign
\nobreak
\tabl_table_set_action\tableunknownstate
- \globalletempty\tabl_tables_check_auto_row
- \globalletempty\tabl_tables_chuck_auto_row
+ \glet\tabl_tables_check_auto_row\empty
+ \glet\tabl_tables_chuck_auto_row\empty
\global\currenttablecolumn\zerocount
\stoptablenoalign}
@@ -1816,21 +1816,21 @@
%D the last row.
\unexpanded\def\tabl_table_AR
- {\globallet\tabl_tables_check_auto_row\tabl_tables_check_auto_row_indeed
- \globallet\tabl_tables_chuck_auto_row\tabl_tables_chuck_auto_row_indeed}
+ {\glet\tabl_tables_check_auto_row\tabl_tables_check_auto_row_indeed
+ \glet\tabl_tables_chuck_auto_row\tabl_tables_chuck_auto_row_indeed}
\let\tabl_tables_check_auto_row\empty
\let\tabl_tables_chuck_auto_row\empty
\def\tabl_tables_check_auto_row_indeed
- {\globallet\tabl_tables_check_auto_row\empty
+ {\glet\tabl_tables_check_auto_row\empty
\ifnum\tableactionstate=\tablerulestate \FR\else
\ifnum\tableactionstate=\tableunknownstate\FR\else
\MR\fi\fi}
\def\tabl_tables_chuck_auto_row_indeed
- {\globalletempty\tabl_tables_check_auto_row
- \globalletempty\tabl_tables_chuck_auto_row
+ {\glet\tabl_tables_check_auto_row\empty
+ \glet\tabl_tables_chuck_auto_row\empty
\ifnum\tableactionstate=\tablerulestate \SR\else
\ifnum\tableactionstate=\tableunknownstate\SR\else
\LR\fi\fi}
@@ -1914,7 +1914,7 @@
\dosingleempty\table_tabl_VL_indeed}
\def\table_tabl_VL_indeed[#1]%
- {\global\let\m_tabl_table_vrule_color\empty
+ {\glet\m_tabl_table_vrule_color\empty
\global\c_tabl_table_vrule_thickness_factor\m_tabl_table_VLwidth\relax
\iffirstargument
\rawprocesscommalist[#1]\tabl_table_vrulecommand
@@ -1961,7 +1961,7 @@
\bgroup
\global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax
\iffirstargument
- \global\let\m_tabl_table_hrule_color\empty
+ \glet\m_tabl_table_hrule_color\empty
\rawprocesscommalist[#1]\tabl_table_hrulecommand
\ifx\m_tabl_table_hrule_color\empty\else
\switchtocolor[\m_tabl_table_hrule_color]%
@@ -2083,7 +2083,7 @@
\global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax
\global\c_tabl_table_drule_span\zerocount
\iffirstargument
- \global\let\m_tabl_table_hrule_color\empty
+ \glet\m_tabl_table_hrule_color\empty
\rawprocesscommalist[#1]\tabl_table_drulecommand
% \ifx\m_tabl_table_hrule_color\empty\else
% \switchtocolor[\m_tabl_table_hrule_color]% see *DL*
diff --git a/tex/context/base/mkiv/tabl-tbl.mkiv b/tex/context/base/mkiv/tabl-tbl.mkiv
index 7a0d2c8a8..75839caed 100644
--- a/tex/context/base/mkiv/tabl-tbl.mkiv
+++ b/tex/context/base/mkiv/tabl-tbl.mkiv
@@ -158,6 +158,7 @@
\newtoks \t_tabl_tabulate_dummy
\newtoks \t_tabl_tabulate_every_row
\newtoks \t_tabl_tabulate_every_after_row
+\newtoks \t_tabl_tabulate_every_real_row
\newtoks \t_tabl_tabulate_initializers_first
\newtoks \t_tabl_tabulate_initializers_second
@@ -174,6 +175,8 @@
\newcount \c_tabl_tabulate_totalnoflines
\newcount \c_tabl_tabulate_minusnoflines
\newcount \c_tabl_tabulate_align
+\newcount \c_tabl_tabulate_nofrealrows
+\newcount \c_tabl_tabulate_autocolor
\newcount \c_tabl_tabulate_nofcolumns % set at the lua end by parser
\newcount \c_tabl_tabulate_has_rule_spec_first % set at the lua end by parser (for the moment a count)
@@ -250,6 +253,18 @@
\installcorenamespace{tabulatefoot}
\installcorenamespace{tabulatenext}
+\prependtoks
+ \global\c_tabl_tabulate_nofrealrows\zerocount
+\to \t_tabl_tabulate_initializers_first
+
+\prependtoks
+ \global\c_tabl_tabulate_nofrealrows\zerocount
+\to \t_tabl_tabulate_initializers_second
+
+\prependtoks
+ \global\advance\c_tabl_tabulate_nofrealrows\plusone
+\to \t_tabl_tabulate_every_real_row
+
\def\b_tabl_tabulate_current#1%
{\csname\??tabulatebox\number#1\endcsname} % beware, a synonym
@@ -354,8 +369,8 @@
\ifx\m_tabl_tabulate_color_local\empty
\xdef\m_tabl_tabulate_color{#1}%
\else
- \global\let\m_tabl_tabulate_color\m_tabl_tabulate_color_local
- \global\let\m_tabl_tabulate_color_local\empty
+ \glet\m_tabl_tabulate_color\m_tabl_tabulate_color_local
+ \glet\m_tabl_tabulate_color_local\empty
\fi
\ifcase\c_tabl_tabulate_localcolorspan
\global\c_tabl_tabulate_colorspan#2\relax
@@ -381,8 +396,8 @@
\ifx\m_tabl_tabulate_vrule_color_local\empty
\xdef\m_tabl_tabulate_vrule_color{#1}%
\else
- \global\let\m_tabl_tabulate_vrule_color\m_tabl_tabulate_vrule_color_local
- \global\let\m_tabl_tabulate_vrule_color_local\empty
+ \glet\m_tabl_tabulate_vrule_color\m_tabl_tabulate_vrule_color_local
+ \glet\m_tabl_tabulate_vrule_color_local\empty
\fi}
\let\tabl_tabulate_check_local_color \gobbletwoarguments
@@ -553,13 +568,13 @@
\installtabulatepreambleoption{i}{\tabl_tabulate_set_preskip}
\installtabulatepreambleoption{j}{\tabl_tabulate_set_posskip}
\installtabulatepreambleoption{k}{\tabl_tabulate_set_preposskip}
-\installtabulatepreambleoption{e}{\t_tabl_tabulate_settings\expandafter{\the\t_tabl_tabulate_settings\global\settrue\c_tabl_tabulate_equal}%
+\installtabulatepreambleoption{e}{\toksapp\t_tabl_tabulate_settings{\global\settrue\c_tabl_tabulate_equal}%
\tabl_tabulate_set_preamble}
\installtabulatepreambleoption{g}{\tabl_tabulate_set_align}
\installtabulatepreambleoption{.}{\tabl_tabulate_set_align.}
\installtabulatepreambleoption{,}{\tabl_tabulate_set_align,}
\installtabulatepreambleoption{C}{\tabl_tabulate_set_color_span}
-\installtabulatepreambleoption{d}{\t_tabl_tabulate_settings\expandafter{\the\t_tabl_tabulate_settings\fixedspaces}%
+\installtabulatepreambleoption{d}{\toksapp\t_tabl_tabulate_settings{\fixedspaces}%
\tabl_tabulate_set_preamble}
\installtabulatepreambleoption{ }{\tabl_tabulate_set_preamble}
\installtabulatepreambleoption{A}{\tabl_tabulate_set_alignment}
@@ -607,18 +622,18 @@
\tabl_tabulate_set_preamble}
\def\tabl_tabulate_set_preskip#1%
- {\doifelsenumber{#1}
- {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble }
+ {\doifelsenumber{#1}%
+ {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble }%
{\s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\tabl_tabulate_set_preamble#1}}
\def\tabl_tabulate_set_posskip#1%
- {\doifelsenumber{#1}
- {\s_tabl_tabulate_post#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble }
+ {\doifelsenumber{#1}%
+ {\s_tabl_tabulate_post#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble }%
{\s_tabl_tabulate_post.5\d_tabl_tabulate_unit\tabl_tabulate_set_preamble#1}}
\def\tabl_tabulate_set_preposskip#1%
- {\doifelsenumber{#1}
- {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble }
+ {\doifelsenumber{#1}%
+ {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble }%
{\s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble#1}}
\def\tabl_tabulate_set_setups#1%
@@ -704,6 +719,28 @@
\fi
\tabl_tabulate_set_preamble}
+% faster but seldom used
+%
+% \installcorenamespace{tabulatewidth}
+%
+% \setvalue{\??tabulatewidth\v!fit }{\c_tabl_tabulate_modus\plusthree}
+% \setvalue{\??tabulatewidth\v!fixed}{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_nopbreak}
+% \setvalue{\??tabulatewidth\v!auto }{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_reshape}
+%
+% \def\tabl_tabulate_set_width_step#1%
+% {\ifcsname\??tabulatewidth#1\endcsname
+% \lastnamedcs
+% \else
+% \d_tabl_tabulate_width#1\relax
+% \fi}
+%
+% \def\tabl_tabulate_set_width_indeed(#1)%
+% {\rawprocesscommacommand[#1]\tabl_tabulate_set_width_step
+% \ifconditional\c_tabl_tabulate_pwidth_set
+% \global\advance\d_tabl_tabulate_width_p\d_tabl_tabulate_width % accumulated parwidth
+% \fi
+% \tabl_tabulate_set_preamble}
+%
\def\tabl_tabulate_set_raggedright {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedright \fi}
\def\tabl_tabulate_set_raggedcenter{\ifnum\c_tabl_tabulate_type=\plusone \else\raggedcenter\fi}
\def\tabl_tabulate_set_raggedleft {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedleft \fi}
@@ -772,10 +809,10 @@
\t_tabl_tabulate_emath\emptytoks
\t_tabl_tabulate_font\emptytoks
\t_tabl_tabulate_settings\emptytoks
- \global\let\m_tabl_tabulate_alignment\empty
- \global\let\m_tabl_tabulate_color\empty
- \global\let\m_tabl_tabulate_text_color\empty
- \global\let\m_tabl_tabulate_vrule_color\empty
+ \glet\m_tabl_tabulate_alignment\empty
+ \glet\m_tabl_tabulate_color\empty
+ \glet\m_tabl_tabulate_text_color\empty
+ \glet\m_tabl_tabulate_vrule_color\empty
\global\c_tabl_tabulate_colorspan\zerocount
\global\setfalse\c_tabl_auto_align_mode
\global\advance\c_tabl_tabulate_columns\plusone
@@ -799,8 +836,8 @@
\fi}
\def\tabl_tabulate_set_last_entry#1% rulespec
- {\global\let\m_tabl_tabulate_color\empty
- \global\let\m_tabl_tabulate_vrule_color\empty
+ {\glet\m_tabl_tabulate_color\empty
+ \glet\m_tabl_tabulate_vrule_color\empty
\edef\currenttabulationtrulespec{#1}%
\ifx\currenttabulationtrulespec\empty
\global\d_tabl_tabulate_vrulethickness\zeropoint
@@ -1176,9 +1213,12 @@
\expandafter\tabl_start_regular_one
\fi}
+\def\tabl_default_format{|l|p|}
+
\def\tabl_start_regular_one[#1][#2]%
{\doifelseassignment{#1}
- {\setupcurrenttabulation[\c!format={|l|p|},#1]}
+ {\lettabulationparameter\c!format\tabl_default_format
+ \setupcurrenttabulation[#1]}
{\def\p_format{#1}%
\ifx\p_format\empty
\def\p_format{|l|p|}%
@@ -1189,7 +1229,7 @@
\def\tabl_start_regular_two[#1][#2]%
{\def\p_format{#1}%
\ifx\p_format\empty
- \def\p_format{|l|p|}%
+ \let\p_format\tabl_default_format
\fi
\lettabulationparameter\c!format\p_format
\setupcurrenttabulation[#2]%
@@ -1278,7 +1318,7 @@
\fi\fi}
\def\tabl_tabulate_outside_after_indeed
- {\tabulationparameter\c!after}%
+ {\tabulationparameter\c!after}
\def\tabl_tabulate_outside_inbetween_indeed
{\doifempty{\tabulationparameter\c!after}
@@ -1313,6 +1353,7 @@
\edef\p_bodyfont {\tabulationparameter\c!bodyfont}
\edef\p_indenting {\tabulationparameter\c!indenting}%
\edef\p_keeptogether {\tabulationparameter\c!keeptogether}%
+ \edef\p_blank {\tabulationparameter\c!blank}%
%
\ifx\p_keeptogether\v!no
\settrue \c_tabl_tabulate_tolerant_break
@@ -1325,6 +1366,8 @@
\settrue\c_tabl_tabulate_split
\csname\??tabulatesplit\tabulationparameter\c!split\endcsname
%
+ \let\m_tabl_tabulate_blank_default\p_blank
+ %
\d_tabl_tabulate_unit\tabulationparameter\c!unit
\d_tabl_tabulate_margin\tabulationparameter\c!margin
\let\m_tabl_tabulate_vrule_color_default\p_rulecolor
@@ -1371,14 +1414,15 @@
\let\m_tabl_tabulate_vrule_color_local \empty
\let\m_tabl_tabulate_vrule_color_default\empty % used local
\let\m_tabl_tabulate_hrule_color_default\empty % used local
+\let\m_tabl_tabulate_blank_default \empty
\appendtoks
- \global\let\m_tabl_tabulate_color_previous \empty
- \global\let\m_tabl_tabulate_color \empty
- \global\let\m_tabl_tabulate_text_color \empty
- \global\let\m_tabl_tabulate_color_local \empty
- \global\let\m_tabl_tabulate_vrule_color \empty
- \global\let\m_tabl_tabulate_vrule_color_local \empty
+ \glet\m_tabl_tabulate_color_previous \empty
+ \glet\m_tabl_tabulate_color \empty
+ \glet\m_tabl_tabulate_text_color \empty
+ \glet\m_tabl_tabulate_color_local \empty
+ \glet\m_tabl_tabulate_vrule_color \empty
+ \glet\m_tabl_tabulate_vrule_color_local \empty
\global \d_tabl_tabulate_vrulethickness_local\zeropoint
\to \t_tabl_tabulate_every_row
@@ -1470,7 +1514,7 @@
% ruled columns
\def\tabl_tabulate_column_vruled_preset
- {\global\let\m_tabl_tabulate_vrule_color_local\m_tabl_tabulate_vrule_color_default
+ {\glet\m_tabl_tabulate_vrule_color_local\m_tabl_tabulate_vrule_color_default
\global\d_tabl_tabulate_vrulethickness_local\d_tabl_tabulate_vrulethickness_default}
\def\tabl_tabulate_column_vruled#1#2%
@@ -1513,7 +1557,7 @@
\global\c_tabl_tabulate_max_vrulecolumn\zerocount}
\def\tabl_tabulate_vrule_reset_step % undefined or relax
- {\global\expandafter\let\csname\??tabulatevrule\the\fastloopindex\endcsname\undefined}
+ {\expandafter\glet\csname\??tabulatevrule\the\fastloopindex\endcsname\undefined}
\appendtoks
\tabl_tabulate_vrule_reset
@@ -1606,12 +1650,12 @@
\egroup}
\def\tabl_tabulate_hrule_spec_ignore#1%
- {%\global\let\currenttabulationlocalhrulecolor\empty
+ {%\glet\currenttabulationlocalhrulecolor\empty
%\global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
\doifelsefastoptionalcheck#1#1}
\def\tabl_tabulate_hrule_spec_pickup#1%
- {\global\let\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default
+ {\glet\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default
\global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
\doifelsefastoptionalcheck{\tabl_tabulate_hrule_preset#1}#1}
@@ -1625,10 +1669,11 @@
#1}
\def\tabl_tabulate_hrule_inject_normal
- {\hrule
- \s!height.5\d_tabl_tabulate_hrulethickness_local
- \s!depth .5\d_tabl_tabulate_hrulethickness_local
- \relax}
+ {\autorule
+ \s!height .5\d_tabl_tabulate_hrulethickness_local
+ \s!depth .5\d_tabl_tabulate_hrulethickness_local
+ \s!left \d_tabl_tabulate_indent
+ \relax}
\def\tabl_tabulate_hrule_inject_colored
{\dousecolorparameter\currenttabulationlocalhrulecolor
@@ -1686,21 +1731,21 @@
\unexpanded\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call
{\begingroup
\clf_enablebackgroundalign % was \node_backgrounds_align_initialize
- \global\let\tabl_tabulate_color_repeat\tabl_tabulate_color_repeat_second
+ \glet\tabl_tabulate_color_repeat\tabl_tabulate_color_repeat_second
\global\settrue\c_tabl_tabulate_has_colors
\ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_colorcolumn
\global\c_tabl_tabulate_max_colorcolumn\c_tabl_tabulate_column
\fi
- \global\expandafter\xdef\csname\??tabulatecolor\the\c_tabl_tabulate_column\endcsname{#1}%
- \hbox \thealignbackgroundcolorattr{#1}{}% pack ?
+ \expandafter\xdef\csname\??tabulatecolor\the\c_tabl_tabulate_column\endcsname{#1}%
+ \hpack \thealignbackgroundcolorattr{#1}{}% pack ?
\endgroup}
\def\tabl_tabulate_color_repeat_second % for split off lines
{\begingroup
\scratchcounter\numexpr\c_tabl_tabulate_column-\plusone\relax % ugly !
\ifcsname\??tabulatecolor\the\scratchcounter\endcsname
- %\hbox \thealignbackgroundcolorattr{\csname\??tabulatecolor\the\scratchcounter\endcsname}{}% pack ?
- \hbox \thealignbackgroundcolorattr{\lastnamedcs}{}% pack ?
+ % \hbox \thealignbackgroundcolorattr{\csname\??tabulatecolor\the\scratchcounter\endcsname}{}% pack ?
+ \hpack \expandafter\thealignbackgroundcolorattr\expandafter{\lastnamedcs}{}% pack ?
\fi
\endgroup}
@@ -1722,7 +1767,7 @@
{\dofastloopcs\c_tabl_tabulate_max_colorcolumn\tabl_tabulate_color_reset_step}
\def\tabl_tabulate_color_reset_step % undefined or empty?
- {\global\expandafter\let\csname\??tabulatecolor\number\fastloopindex\endcsname\undefined}
+ {\expandafter\glet\csname\??tabulatecolor\number\fastloopindex\endcsname\undefined}
\appendtoks
\tabl_tabulate_color_reset
@@ -1771,17 +1816,20 @@
\tabl_tabulate_register_par_options
\to \t_tabl_tabulate_every_row
+\def\tabl_tabulate_flush_indent_indeed
+ {\hbox to \d_tabl_tabulate_indent % pack ?
+ {% we now have a local hsize, and since we want to
+ % register positional info (i.e. real hsizes) we
+ % need to reconstitute the original hsize
+ \advance\hsize\d_tabl_tabulate_indent
+ % this is indeed rather messy and took a few hours
+ % to dis/uncover
+ \the\t_tabl_tabulate_every_row
+ \hss}}
+
\def\tabl_tabulate_flush_indent
{\ifnum\c_tabl_tabulate_column=\zerocount
- \hbox to \d_tabl_tabulate_indent % pack ?
- {% we now have a local hsize, and since we want to
- % register positional info (i.e. real hsizes) we
- % need to reconstitute the original hsize
- \advance\hsize\d_tabl_tabulate_indent
- % this is indeed rather messy and took a few hours
- % to dis/uncover
- \the\t_tabl_tabulate_every_row
- \hss}%
+ \tabl_tabulate_flush_indent_indeed
\fi}
\def\tabl_tabulate_digits{\digits}
@@ -1800,7 +1848,7 @@
\unexpanded\def\tabl_tabulate_bskip_first {\setbox\b_tabl_tabulate\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
\unexpanded\def\tabl_tabulate_eskip_first {\par\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
-\unexpanded\def\tabl_tabulate_xbskip_first{\hbox\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
+\unexpanded\def\tabl_tabulate_xbskip_first{\hpack\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
\unexpanded\def\tabl_tabulate_xeskip_first{\par\egroup\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
\let\tabl_tabulate_bbskip\relax
@@ -1831,12 +1879,12 @@
% \def\tabl_tabulate_break_state_set
% {%\writestatus{SET}{\the\c_tabl_tabulate_noflines}%
-% \global\expandafter\let\csname\??tabulatenobreak\the\c_tabl_tabulate_noflines\endcsname\conditionaltrue}
+% \expandafter\glet\csname\??tabulatenobreak\the\c_tabl_tabulate_noflines\endcsname\conditionaltrue}
%
% \def\tabl_tabulate_break_state_reset
% {\ifcsname\??tabulatenobreak\the\c_tabl_tabulate_noflines\endcsname
% %\writestatus{RESET}{\the\c_tabl_tabulate_noflines}%
-% \global\expandafter\let\csname\??tabulatenobreak\the\c_tabl_tabulate_noflines\endcsname\undefined
+% \expandafter\glet\csname\??tabulatenobreak\the\c_tabl_tabulate_noflines\endcsname\undefined
% \fi}
%
% \def\tabl_tabulate_break_state_allowbreak
@@ -1912,8 +1960,6 @@
%D
%D \typebuffer \getbuffer
-\let\NI\relax
-
\unexpanded\def\tabl_tabulate_NI_first{\doifelsefastoptionalcheck\tabl_tbl_NI_yes\tabl_tbl_NI_nop}
\def\tabl_tbl_NI_yes[#1]{\NC \itemtag[#1]\NC}
@@ -2189,7 +2235,7 @@
% \def\tabulatedoHRfive % horizontal rule line (break untested)
% {\starttabulatenoalign
-% \globallet\dotabulateautoline\dotabulatelinerule
+% \glet\dotabulateautoline\dotabulatelinerule
% %\ifcase#1\or % todo: check what this does
% \ifnum\noftabulatelines=\zerocount
% \glet\dotabulateautoline\donothing
@@ -2204,9 +2250,9 @@
% \tabl_tabulate_break_no
% \ifx\dotabulateautoline\dotabulatelinerule\kern-\lineheight\fi
% \ifnum\noftabulatelines=\totalnoftabulatelines
-% \@EA\dotabulatenobreak
+% \expandafter\dotabulatenobreak
% \else
-% \@EA\tabl_tabulate_break_allow
+% \expandafter\tabl_tabulate_break_allow
% \fi
% \stoptabulatenoalign
% \dotabulateautoline
@@ -2403,8 +2449,8 @@
\dostarttaggedchained\t!tabulate\empty\??tabulation
\dostarttagged\t!tabulaterow\empty
\setfalse\inhibitmargindata % new per 2012.06.13 ... really needed
- \everycr\expandafter{\the\everycr\dostoptagged\dostarttagged\t!tabulaterow\empty}%
- % \toksapp\everycr{\dostoptagged\dostarttagged\t!tabulaterow\empty}%
+ % \everycr\expandafter{\the\everycr\noalign{\the\t_tabl_tabulate_every_real_row}\dostoptagged\dostarttagged\t!tabulaterow\empty}%
+ \toksapp\everycr{\noalign{\the\t_tabl_tabulate_every_real_row}\dostoptagged\dostarttagged\t!tabulaterow\empty}%
\expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}%
\dostoptagged
\dostoptagged
@@ -2504,9 +2550,11 @@
\def\tabl_tabulate_TB_indeed[#1]%
{\iffirstargument
\blank[#1]
- \else
+ \else\ifx\m_tabl_tabulate_blank_default\empty
\blank
- \fi
+ \else
+ \blank[\m_tabl_tabulate_blank_default]%
+ \fi\fi
\stoptabulatenoalign}
% to be tested:
@@ -2729,4 +2777,295 @@
\unexpanded\def\tabulaterowtype{\tabl_tabulate_compact_row\type}
\unexpanded\def\tabulaterowtyp {\tabl_tabulate_compact_row\typ}
+%D Here we plug in a row background feature. As we only have support for
+%D \type {frame=name} we can use these variables.
+%D
+%D \starttyping
+%D \startuseMPgraphic{foo}
+%D fill unitsquare
+%D xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8)
+%D randomized ExHeight
+%D shifted (-ExHeight/8,ExHeight/16)
+%D withcolor RuleColor ;
+%D \stopuseMPgraphic
+%D
+%D \setuptabulate % wel only have frame=name so we can use these:
+%D [background=foo,
+%D backgroundcolor=darkred,
+%D foregroundcolor=white]
+%D
+%D \definelinefiller[foo][mp=foo,color=darkgreen]
+%D \definelinefiller[bar][mp=foo,color=darkred]
+%D
+%D \starttabulate[|||]
+%D \DB foo \BC bar \BC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \stoptabulate
+%D
+%D \starttabulate[|||]
+%D \PB foo \BC bar \BC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \stoptabulate
+%D
+%D \starttabulate[|||]
+%D \FB[bar] foo \BC bar \BC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \stoptabulate
+%D
+%D \startnarrower
+%D \starttabulate[|||]
+%D \DB foo \DB bar \BC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \stoptabulate
+%D \stopnarrower
+%D
+%D \starttabulate[|||]
+%D \BC foo \BC bar \BC \NR
+%D \NL[magenta] foo \NC bar \NC \NR
+%D \NL[yellow] foo \NC bar \NC \NR
+%D \NL[cyan] foo \NC bar \NC \NR
+%D \NL[gray] foo \NC bar \NC \NR
+%D \stoptabulate
+%D
+%D \starttabulate
+%D \NL[red] foo \NC bar \NC \NR
+%D \NL[green] foo \NL[red] bar \NC \NR
+%D \NC foo \NC bar \NC \NR
+%D \NL[blue] foo \NC \input tufte \NC \NR
+%D \NL[gray] foo \NC bar \NC \NR
+%D \NL[yellow] foo \NC bar \NC \NR
+%D \stoptabulate
+%D \stoptyping
+
+% \setuptabulate
+% [\c!background=,
+% \c!backgroundcolor=,
+% \c!foregroundcolor=,
+% \c!foregroundstyle=]
+
+\let\m_table_current_row_background \empty
+\let\m_table_current_row_background_default \empty
+\let\m_table_current_row_background_filler \empty
+\let\m_table_current_row_background_defaultfiller\empty
+\let\m_table_current_row_background_auto \empty
+
+\unexpanded\def\tabl_register_row_background#1%
+ {\xdef\m_table_current_row_background{#1}}
+
+\unexpanded\def\tabl_register_row_background_filler#1%
+ {\xdef\m_table_current_row_background_filler{#1}}
+
+\unexpanded\def\tabl_synchronize_row_background
+ {\iftrialtypesetting\else
+ \ifx\m_table_current_row_background_filler\empty
+ \ifx\m_table_current_row_background\empty
+ % nothing
+ \tabl_synchronize_row_background_dummy
+ \else
+ \tabl_synchronize_row_background_indeed\m_table_current_row_background
+ \fi
+ \else
+ \tabl_synchronize_row_background_filler_indeed\m_table_current_row_background_filler
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_synchronize_row_background_dummy
+ {\iftrialtypesetting\else
+ \begingroup
+ %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\zerocount\zeropoint
+ \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\zerocount\zeropoint
+ \endgroup
+ \fi}
+
+\unexpanded\def\tabl_synchronize_row_background_indeed#1%
+ {\iftrialtypesetting\else
+ \begingroup
+ \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata
+ \dousecolorparameter{#1}%
+ \setbox\scratchbox\hpack{}%
+ %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent
+ \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent
+ \endgroup
+ \fi}
+
+\unexpanded\def\tabl_synchronize_row_background_filler_indeed#1%
+ {\iftrialtypesetting\else
+ \begingroup
+ \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata
+ \node_linefiller_set{#1}%
+ \setbox\scratchbox\hpack{}%
+ %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent
+ \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent
+ \endgroup
+ \fi}
+
+\appendtoks
+ \glet\m_table_current_row_background\empty
+ \glet\m_table_current_row_background_filler\empty
+ \global\c_tabl_tabulate_nofrealrows\zerocount
+ \global\c_tabl_tabulate_autocolor\zerocount
+ \clf_resetbackgroundrowdata
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \glet\m_table_current_row_background\empty
+ \glet\m_table_current_row_background_filler\empty
+ \global\c_tabl_tabulate_nofrealrows\zerocount
+ \global\c_tabl_tabulate_autocolor\zerocount
+ \clf_resetbackgroundrowdata
+\to \t_tabl_tabulate_initializers_second
+
+\appendtoks
+ \tabl_synchronize_row_background
+\to \t_tabl_tabulate_every_real_row
+
+\appendtoks
+ \glet\m_table_current_row_background\empty
+ \glet\m_table_current_row_background_filler\empty
+\to \t_tabl_tabulate_every_after_row
+
+\unexpanded\def\tabl_tabulate_NL_first[#1]%
+ {\tabl_tabulate_column_normal\zerocount\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background{#1}%
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_ND_first
+ {\tabl_tabulate_column_normal\zerocount\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background\m_table_current_row_background_default
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_LB_first[#1]%
+ {\tabl_tabulate_column_normal\plusone\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background{#1}%
+ \fi
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_DB_first
+ {\tabl_tabulate_column_normal\plusone\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background\m_table_current_row_background_default
+ \fi
+ \let\fontstyle\globalfontstyle
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_NF_first[#1]%
+ {\tabl_tabulate_column_normal\zerocount\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background_filler{#1}%
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_NP_first
+ {\tabl_tabulate_column_normal\zerocount\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background_filler\m_table_current_row_background_default_filler
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_FB_first[#1]%
+ {\tabl_tabulate_column_normal\plusone\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background_filler{#1}%
+ \fi
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_PB_first
+ {\tabl_tabulate_column_normal\plusone\zerocount\relax
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_register_row_background_filler\m_table_current_row_background_default_filler
+ \fi
+ \let\fontstyle\globalfontstyle
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_BC_first % overloaded
+ {\tabl_tabulate_column_normal\plusone\zerocount
+ \let\fontstyle\globalfontstyle
+ \ifx\m_table_current_row_background\empty
+ \ifx\m_table_current_row_background_filler\empty
+ \usetabulationstyleandcolor\c!headstyle\c!headcolor
+ \else
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \fi
+ \else
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \fi}
+
+\unexpanded\def\tabl_tabulate_A_first
+ {\global\advance\c_tabl_tabulate_autocolor\plusone
+ \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}%
+ \ifx\m_table_current_row_background_auto\empty
+ \global\c_tabl_tabulate_autocolor\plusone
+ \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}%
+ \fi
+ \ifx\m_table_current_row_background_auto\empty
+ \let\m_table_current_row_background_auto\empty % \m_table_current_row_background_default
+ \fi
+ \tabl_register_row_background{\m_table_current_row_background_auto}}
+
+\unexpanded\def\tabl_tabulate_NA_first
+ {\tabl_tabulate_column_normal\zerocount\zerocount\relax
+ \iftrialtypesetting\else
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_tabulate_A_first
+ \fi
+ \fi
+ \ignorespaces}
+
+\unexpanded\def\tabl_tabulate_BA_first
+ {\tabl_tabulate_column_normal\plusone\zerocount\relax
+ \iftrialtypesetting\else
+ \ifcase\c_tabl_tabulate_column\or
+ \tabl_tabulate_A_first
+ \fi
+ \fi
+ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
+ \ignorespaces}
+
+\appendtoks
+ \let\NL\tabl_tabulate_NL_first % NC with Line
+ \let\ND\tabl_tabulate_ND_first % NC with Default Line
+ \let\LB\tabl_tabulate_LB_first % BC with Line
+ \let\DB\tabl_tabulate_DB_first % BC with Default Line
+ \let\NF\tabl_tabulate_NF_first % NC with Filler
+ \let\NP\tabl_tabulate_NP_first % NC with Predefined Filler
+ \let\FB\tabl_tabulate_FB_first % BC with Filler
+ \let\PB\tabl_tabulate_PB_first % BC with Predefined Filler
+ \let\NA\tabl_tabulate_NA_first % NC with Auto Line
+ \let\BA\tabl_tabulate_BA_first % NC with Auto Line
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \edef\m_table_current_row_background_default {\tabulateparameter\c!backgroundcolor}%
+ \edef\m_table_current_row_background_default_filler{\tabulateparameter\c!background}%
+ \let \m_table_current_row_background_auto \empty
+\to \everytabulate
+
+\setuptabulate
+ [\c!headcolor=,
+ \c!headstyle=\bf,
+ \c!backgroundcolor=\tabulationparameter\c!rulecolor,
+ \c!foregroundcolor=,
+ \c!foregroundstyle=\tabulationparameter\c!headstyle]
+
\protect \endinput
diff --git a/tex/context/base/mkiv/tabl-tsp.mkiv b/tex/context/base/mkiv/tabl-tsp.mkiv
index 2c4b694b3..e0ddce38a 100644
--- a/tex/context/base/mkiv/tabl-tsp.mkiv
+++ b/tex/context/base/mkiv/tabl-tsp.mkiv
@@ -441,6 +441,35 @@
\exitloop
\fi\fi}
+%D Maybe handy:
+%D
+%D \starttyping
+%D \splitfloat
+%D {\placefigure{some caption}}
+%D {\startsplittext
+%D \typefile[option=TEX,before=,after=]{oeps.tex}
+%D \stopsplittext}
+%D \stoptyping
+
+\def\handlesplittext#1%
+ {\setbox\tsplitresult\vbox
+ {\vsplit\tsplitcontent to \dimexpr#1-\lineheight\relax}}
+
+\unexpanded\def\startsplittext
+ {\begingroup
+ \resettsplit
+ \let\tsplitminimumfreelines\!!zerocount
+ \let\tsplitminimumfreespace\!!zeropoint
+ \let\extrasplitfloatlines \!!plusone
+ \let\tsplitdirectsplitter \handlesplittext
+ \setbox\tsplitcontent\vbox\bgroup
+ \insidefloattrue}
+
+\unexpanded\def\stopsplittext
+ {\egroup
+ \handledirecttsplit
+ \endgroup}
+
\protect \endinput
% test cases
diff --git a/tex/context/base/mkiv/tabl-xtb.lua b/tex/context/base/mkiv/tabl-xtb.lua
index 524ca109c..c9d50638e 100644
--- a/tex/context/base/mkiv/tabl-xtb.lua
+++ b/tex/context/base/mkiv/tabl-xtb.lua
@@ -70,7 +70,7 @@ local getbox = nuts.getbox
local getwhd = nuts.getwhd
local setlink = nuts.setlink
-local setdir = nuts.setdir
+local setdirection = nuts.setdirection
local setshift = nuts.setshift
local copy_node_list = nuts.copy_list
@@ -84,6 +84,8 @@ local new_glue = nodepool.glue
local new_kern = nodepool.kern
local new_hlist = nodepool.hlist
+local lefttoright_code = nodes.dirvalues.lefttoright
+
local v_stretch = variables.stretch
local v_normal = variables.normal
local v_width = variables.width
@@ -375,7 +377,8 @@ function xtables.set_reflow_width()
--
drc.dimensionstate = dimensionstate
--
- local nx, ny = drc.nx, drc.ny
+ local nx = drc.nx
+ local ny = drc.ny
if nx > 1 or ny > 1 then
-- local spans = data.spans -- not used
local self = true
@@ -886,13 +889,13 @@ function xtables.construct()
-- we have a direction issue here but hpack_node_list(list,0,"exactly","TLT") cannot be used
-- due to the fact that we need the width
local hbox = hpack_node_list(list)
- setdir(hbox,"TLT")
+ setdirection(hbox,lefttoright_code)
result[nofr] = {
hbox,
size,
i < nofrange and rowdistance > 0 and rowdistance or false, -- might move
false,
- rp and rp.samepage or false,
+ rp or false,
}
end
end
@@ -901,7 +904,7 @@ function xtables.construct()
result[1] [5] = false
result[nofr][5] = false
for i=2,nofr-1 do
- local r = result[i]
+ local r = result[i][5]
if r == v_both or r == v_before then
result[i-1][5] = true
elseif r == v_after then
diff --git a/tex/context/base/mkiv/tabl-xtb.mkvi b/tex/context/base/mkiv/tabl-xtb.mkvi
index dc4a30e2b..148304331 100644
--- a/tex/context/base/mkiv/tabl-xtb.mkvi
+++ b/tex/context/base/mkiv/tabl-xtb.mkvi
@@ -102,6 +102,10 @@
\newcount\c_tabl_x_nesting
\newcount\c_tabl_x_skip_mode % 1 = skip
\newdimen\d_tabl_x_textwidth
+\newcount\c_tabl_x_swapped
+\newcount\c_tabl_x_swapped_max
+
+\let\m_tabl_x_swapped_settings\empty
\let\currentxtablerow \clf_x_table_r
\let\currentxtablecolumn\clf_x_table_c
@@ -112,6 +116,7 @@
\installcorenamespace{xtable}
\installcorenamespace{xtablecheck}
+\installcorenamespace{xtableswap}
\installframedautocommandhandler \??xtable {xtable} \??xtable
@@ -271,6 +276,8 @@
\let\tabl_x_start_cell_nop\relax
\let\tabl_x_stop_cell \relax
+\newtoks\t_table_x_cleanup
+
\unexpanded\def\tabl_x_process
{\begingroup % *
\forgetall % moved here
@@ -296,6 +303,7 @@
% not so nice but needed as we use this in the setup
\linewidth\xtableparameter\c!rulethickness\relax
% so we freeze it
+ \c_tabl_x_swapped_max\zerocount
\begingroup
\let\tabl_x_start_row_yes \tabl_x_start_row_reflow_width_yes
\let\tabl_x_start_row_nop \tabl_x_start_row_reflow_width_nop
@@ -305,6 +313,10 @@
\let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_width
\settrialtypesetting
\tabl_x_get_buffer
+ \ifcase\c_tabl_x_swapped_max
+ \else
+ \tabl_x_flush_swapped
+ \fi
\clf_x_table_reflow_width
\endgroup
\begingroup
@@ -315,7 +327,11 @@
\let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_height_nop
\let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_height
\settrialtypesetting
- \tabl_x_get_buffer
+ \ifcase\c_tabl_x_swapped_max
+ \tabl_x_get_buffer
+ \else
+ \tabl_x_flush_swapped
+ \fi
\clf_x_table_reflow_height
\endgroup
\begingroup
@@ -325,7 +341,11 @@
\let\tabl_x_start_cell_yes\tabl_x_start_cell_construct_yes
\let\tabl_x_start_cell_nop\tabl_x_start_cell_construct_nop
\let\tabl_x_stop_cell \tabl_x_stop_cell_construct
- \tabl_x_get_buffer
+ \ifcase\c_tabl_x_swapped_max
+ \tabl_x_get_buffer
+ \else
+ \tabl_x_flush_swapped
+ \fi
\clf_x_table_construct
\endgroup
\endgroup % *
@@ -340,6 +360,7 @@
\dostoptagged
\resetbuffer[\tabl_x_current_buffer]%
\resetcharacteralign
+ \the\t_table_x_cleanup
\egroup}
% text flow split modes
@@ -477,10 +498,6 @@
\unexpanded\def\stopxcell
{\tabl_x_stop_cell}
-\unexpanded\def\dummyxcell#1%
- {\tabl_x_start_cell_nop
- \tabl_x_stop_cell}
-
\unexpanded\def\dummyxcell
{\tabl_x_start_cell_nop
\tabl_x_stop_cell}
@@ -879,4 +896,124 @@
\let\NR\tabl_x_nr
\to \everypreparextable
+%D Another bonus, suggested by Taco at the 2018 \CONTEXT\ meeting.
+
+\unexpanded\def\tabl_x_c_cell_start#settings%
+ {\begingroup
+ \tabl_x_set_checked{#settings}%
+ \doifelsenextoptionalcs\tabl_x_start_cell_yes\tabl_x_start_cell_nop}
+
+\unexpanded\def\tabl_x_c_cell_stop
+ {\tabl_x_stop_cell
+ \endgroup}
+
+% \unexpanded\def\dummyxcell
+% {\tabl_x_start_cell_nop
+% \tabl_x_stop_cell}
+
+\def\tabl_x_flush_swapped
+ {\dorecurse\c_tabl_x_swapped_max
+ {\expandafter
+ \startxrow
+ \the\csname\??xtableswap##1\endcsname\relax
+ \stopxrow}}
+
+\def\tabl_x_collect_allocate
+ {\expandafter\newtoks\csname\??xtableswap\number\c_tabl_x_swapped\endcsname
+ \expandafter\let\expandafter\t_tabl_x_swapped\csname\??xtableswap\number\c_tabl_x_swapped\endcsname}
+
+\def\tabl_x_collect_advance
+ {\global\advance\c_tabl_x_swapped\plusone
+ \ifnum\c_tabl_x_swapped>\c_tabl_x_swapped_max
+ \global\c_tabl_x_swapped_max\c_tabl_x_swapped
+ \fi
+ \expandafter\let\expandafter\t_tabl_x_swapped\csname\??xtableswap\number\c_tabl_x_swapped\endcsname
+ \ifx\t_tabl_x_swapped\relax
+ \tabl_x_collect_allocate
+ \fi}
+
+\unexpanded\def\tabl_x_collect_cell_start
+ {\doifelsenextoptionalcs
+ \tabl_x_collect_cell_start_yes
+ \tabl_x_collect_cell_start_nop}
+
+\def\tabl_x_collect_cell_start_nop#content\stopxcell
+ {\tabl_x_collect_advance
+ \ifx\m_tabl_x_swapped_settings\empty
+ \gtoksapp\t_tabl_x_swapped{\tabl_x_c_cell_start{}#content\tabl_x_c_cell_stop}%
+ \else
+ \gtoksapp\t_tabl_x_swapped\expandafter{\expandafter\tabl_x_c_cell_start\expandafter{\m_tabl_x_swapped_settings}#content\tabl_x_c_cell_stop}%
+ \fi}
+
+\def\tabl_x_collect_cell_start_yes[#settings]#content\stopxcell
+ {\tabl_x_collect_advance
+ \ifx\m_tabl_x_swapped_settings\empty
+ \gtoksapp\t_tabl_x_swapped{\tabl_x_c_cell_start{}[#settings]#content\tabl_x_c_cell_stop}%
+ \else
+ \gtoksapp\t_tabl_x_swapped\expandafter{\expandafter\tabl_x_c_cell_start\expandafter{\m_tabl_x_swapped_settings}[#settings]#content\tabl_x_c_cell_stop}%
+ \fi
+ \getdummyparameters[\c!ny=1,#settings]%
+ \scratchcounter\numexpr\dummyparameter\c!ny-\plusone\relax
+ \ifcase\scratchcounter\else
+ \dorecurse\scratchcounter\tabl_x_collect_advance
+ \fi}
+
+\unexpanded\def\startxcolumn % todo: arguments
+ {\begingroup
+ \global\c_tabl_x_swapped\zerocount
+ \let\startxcell\tabl_x_collect_cell_start
+ \let\stopxcell \relax
+ \doifelsenextoptionalcs\tabl_x_start_column_yes\tabl_x_start_column_nop}
+
+\def\tabl_x_start_column_yes[#1]%
+ {\xdef\m_tabl_x_swapped_settings{#1}}
+
+\def\tabl_x_start_column_nop
+ {\glet\m_tabl_x_swapped_settings\empty}
+
+\unexpanded\def\stopxcolumn
+ {\endgroup}
+
+\appendtoks
+ \dorecurse\c_tabl_x_swapped_max
+ {\global\csname\??xtableswap\number#1\endcsname\emptytoks}%
+\to \t_table_x_cleanup
+
+%D \stopbuffer
+%D \setupxtable[one][foregroundcolor=red]
+%D \setupxtable[two][foregroundcolor=blue]
+%D
+%D \startlinecorrection
+%D \startxtable
+%D \startxrow[one]
+%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell
+%D \startxcell Row 1, Column 2 \stopxcell
+%D \startxcell Row 1, Column 3 \stopxcell
+%D \stopxrow
+%D \startxrow[two]
+%D \startxcell Row 2, Column 1 \stopxcell
+%D \startxcell Row 2, Column 2 \stopxcell
+%D \startxcell Row 2, Column 3 \stopxcell
+%D \stopxrow
+%D \stopxtable
+%D \stoplinecorrection
+%D
+%D \startlinecorrection
+%D \startxtable
+%D \startxcolumn[one]
+%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell
+%D \startxcell Row 1, Column 2 \stopxcell
+%D \startxcell Row 1, Column 3 \stopxcell
+%D \stopxcolumn
+%D \startxcolumn[two]
+%D \startxcell Row 2, Column 1 \stopxcell
+%D \startxcell Row 2, Column 2 \stopxcell
+%D \startxcell Row 2, Column 3 \stopxcell
+%D \stopxcolumn
+%D \stopxtable
+%D \stoplinecorrection
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
\protect \endinput
diff --git a/tex/context/base/mkiv/task-ini.lua b/tex/context/base/mkiv/task-ini.lua
index f41fb9b08..19fff66b8 100644
--- a/tex/context/base/mkiv/task-ini.lua
+++ b/tex/context/base/mkiv/task-ini.lua
@@ -18,224 +18,132 @@ if not modules then modules = { } end modules ['task-ini'] = {
-- not apply the font handler, we can remove all checks for subtypes 255
local tasks = nodes.tasks
-local prependaction = tasks.prependaction
local appendaction = tasks.appendaction
local disableaction = tasks.disableaction
local enableaction = tasks.enableaction
local freezegroup = tasks.freezegroup
local freezecallbacks = callbacks.freeze
-appendaction("processors", "normalizers", "languages.replacements.handler") -- disabled
-
-appendaction("processors", "normalizers", "typesetters.wrappers.handler") -- disabled
-appendaction("processors", "normalizers", "typesetters.characters.handler") -- always on
-appendaction("processors", "normalizers", "fonts.collections.process") -- disabled
-appendaction("processors", "normalizers", "fonts.checkers.missing") -- disabled
-
-appendaction("processors", "characters", "scripts.autofontfeature.handler")
-appendaction("processors", "characters", "scripts.splitters.handler") -- disabled
-appendaction("processors", "characters", "typesetters.cleaners.handler") -- disabled
-appendaction("processors", "characters", "typesetters.directions.handler") -- disabled
-appendaction("processors", "characters", "typesetters.cases.handler") -- disabled
-appendaction("processors", "characters", "typesetters.breakpoints.handler") -- disabled
-appendaction("processors", "characters", "scripts.injectors.handler") -- disabled
-
-------------("processors", "words", "languages.replacements.handler") -- disabled
-appendaction("processors", "words", "languages.words.check") -- disabled -- might move up, no disc check needed then
-appendaction("processors", "words", "languages.hyphenators.handler") -- always on
-appendaction("processors", "words", "typesetters.initials.handler") -- disabled -- might move up
-appendaction("processors", "words", "typesetters.firstlines.handler") -- disabled
-
-appendaction("processors", "fonts", "builders.paragraphs.solutions.splitters.split") -- experimental
-appendaction("processors", "fonts", "nodes.handlers.characters") -- maybe todo
-appendaction("processors", "fonts", "nodes.injections.handler")
-appendaction("processors", "fonts", "typesetters.fontkerns.handler")
-appendaction("processors", "fonts", "nodes.handlers.protectglyphs", nil, "nohead") -- maybe todo
-appendaction("processors", "fonts", "builders.kernel.ligaturing") -- not always on (could be selective: if only node mode)
-appendaction("processors", "fonts", "builders.kernel.kerning") -- not always on (could be selective: if only node mode)
-appendaction("processors", "fonts", "nodes.handlers.stripping") -- disabled (might move)
-------------("processors", "fonts", "typesetters.italics.handler") -- disabled (after otf/kern handling)
-appendaction("processors", "fonts", "nodes.handlers.flatten")
-
-appendaction("processors", "lists", "typesetters.rubies.check") -- disabled (maybe someplace else)
-appendaction("processors", "lists", "typesetters.characteralign.handler") -- disabled (we need to to this after otf appliance)
-appendaction("processors", "lists", "typesetters.spacings.handler") -- disabled
-appendaction("processors", "lists", "typesetters.kerns.handler") -- disabled
-appendaction("processors", "lists", "typesetters.digits.handler") -- disabled (after otf handling)
-appendaction("processors", "lists", "typesetters.italics.handler") -- disabled (after otf/kern handling)
-appendaction("processors", "lists", "languages.visualizediscretionaries") -- disabled
-
-appendaction("processors", "after", "typesetters.marksuspects")
-
-appendaction("shipouts", "normalizers", "typesetters.showsuspects")
-appendaction("shipouts", "normalizers", "typesetters.margins.finalhandler") -- disabled
-------------("shipouts", "normalizers", "nodes.handlers.cleanuppage") -- disabled
-appendaction("shipouts", "normalizers", "builders.paragraphs.expansion.trace") -- disabled
-appendaction("shipouts", "normalizers", "typesetters.alignments.handler") -- disabled
-appendaction("shipouts", "normalizers", "nodes.references.handler") -- disabled
-appendaction("shipouts", "normalizers", "nodes.destinations.handler") -- disabled
-appendaction("shipouts", "normalizers", "nodes.rules.handler") -- disabled
-appendaction("shipouts", "normalizers", "nodes.shifts.handler") -- disabled
-appendaction("shipouts", "normalizers", "structures.tags.handler") -- disabled
-appendaction("shipouts", "normalizers", "nodes.handlers.accessibility") -- disabled
-appendaction("shipouts", "normalizers", "nodes.handlers.backgrounds") -- disabled
-appendaction("shipouts", "normalizers", "nodes.handlers.alignbackgrounds") -- disabled
-------------("shipouts", "normalizers", "nodes.handlers.export") -- disabled
-appendaction("shipouts", "normalizers", "typesetters.rubies.attach") -- disabled
-
-appendaction("shipouts", "finishers", "nodes.visualizers.handler") -- disabled
-appendaction("shipouts", "finishers", "attributes.colors.handler") -- disabled
-appendaction("shipouts", "finishers", "attributes.transparencies.handler") -- disabled
-appendaction("shipouts", "finishers", "attributes.colorintents.handler") -- disabled
-appendaction("shipouts", "finishers", "attributes.negatives.handler") -- disabled
-appendaction("shipouts", "finishers", "attributes.effects.handler") -- disabled
-appendaction("shipouts", "finishers", "attributes.viewerlayers.handler") -- disabled
-
---maybe integrate relocate and families
-
-appendaction("math", "normalizers", "noads.handlers.showtree", nil, "nohead")
-
-appendaction("math", "normalizers", "noads.handlers.unscript", nil, "nohead") -- always on (maybe disabled)
-appendaction("math", "normalizers", "noads.handlers.variants", nil, "nohead") -- always on
-appendaction("math", "normalizers", "noads.handlers.relocate", nil, "nohead") -- always on
-appendaction("math", "normalizers", "noads.handlers.families", nil, "nohead") -- always on
-
-appendaction("math", "normalizers", "noads.handlers.render", nil, "nohead") -- always on
-appendaction("math", "normalizers", "noads.handlers.collapse", nil, "nohead") -- disabled
-appendaction("math", "normalizers", "noads.handlers.fixscripts",nil, "nohead") -- * first-- always on
-appendaction("math", "normalizers", "noads.handlers.domains", nil, "nohead") -- * last -- disabled
-appendaction("math", "normalizers", "noads.handlers.autofences",nil, "nohead") -- disabled
-appendaction("math", "normalizers", "noads.handlers.resize", nil, "nohead") -- always on
-------------("math", "normalizers", "noads.handlers.respace", nil, "nohead") -- always on
-appendaction("math", "normalizers", "noads.handlers.alternates",nil, "nohead") -- always on
-appendaction("math", "normalizers", "noads.handlers.tags", nil, "nohead") -- disabled
-appendaction("math", "normalizers", "noads.handlers.italics", nil, "nohead") -- disabled
-appendaction("math", "normalizers", "noads.handlers.kernpairs", nil, "nohead") -- disabled
-appendaction("math", "normalizers", "noads.handlers.classes", nil, "nohead") -- disabled
-
-appendaction("math", "builders", "builders.kernel.mlist_to_hlist") -- always on
-------------("math", "builders", "noads.handlers.italics", nil, "nohead") -- disabled
-appendaction("math", "builders", "typesetters.directions.processmath") -- disabled (has to happen pretty late)
-appendaction("math", "builders", "noads.handlers.makeup", nil, "nohead") -- disabled (has to happen last)
-appendaction("math", "builders", "noads.handlers.align", nil, "nohead")
-
-appendaction("finalizers", "lists", "typesetters.paragraphs.normalize") -- moved here
-appendaction("finalizers", "lists", "typesetters.margins.localhandler") -- disabled
-appendaction("finalizers", "lists", "builders.paragraphs.keeptogether")
-------------("finalizers", "lists", "nodes.handlers.graphicvadjust") -- todo
-appendaction("finalizers", "fonts", "builders.paragraphs.solutions.splitters.optimize") -- experimental
-appendaction("finalizers", "lists", "builders.paragraphs.tag")
-
--- the next can also be in contributers normalizers (when we remove the loop in the handler)
-
-appendaction("finalizers", "lists", "nodes.linefillers.handler")
-
-appendaction("contributers", "normalizers", "nodes.handlers.flattenline")
-appendaction("contributers", "normalizers", "nodes.handlers.textbackgrounds")
-
--- still experimental
-
-appendaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler") -- disabled
-appendaction("mvlbuilders", "normalizers", "nodes.handlers.migrate")
-
-appendaction("mvlbuilders", "normalizers", "builders.vspacing.pagehandler") -- last !
-appendaction("mvlbuilders", "normalizers", "builders.profiling.pagehandler") -- here !
-
-------------("vboxbuilders", "normalizers", "typesetters.margins.localhandler")
-appendaction("vboxbuilders", "normalizers", "builders.vspacing.vboxhandler")
-appendaction("vboxbuilders", "normalizers", "builders.profiling.vboxhandler") -- here !
-
--- experimental too
-
-appendaction("mvlbuilders", "normalizers", "typesetters.checkers.handler")
-appendaction("vboxbuilders", "normalizers", "typesetters.checkers.handler")
-
--- rather special (this might get hardcoded):
-
-prependaction("processors", "before", "nodes.properties.attach") -- enabled but optimized for quick abort
-appendaction ("shipouts", "normalizers", "nodes.properties.delayed") -- enabled but optimized for quick abort
-
--- speedup: only kick in when used
-
-disableaction("processors", "typesetters.wrappers.handler")
-disableaction("processors", "languages.replacements.handler")
-disableaction("processors", "typesetters.characteralign.handler")
-disableaction("processors", "scripts.autofontfeature.handler")
-disableaction("processors", "scripts.splitters.handler")
-disableaction("processors", "scripts.injectors.handler") -- was enabled
-disableaction("processors", "fonts.collections.process")
-disableaction("processors", "fonts.checkers.missing")
-disableaction("processors", "chars.handle_breakpoints")
-disableaction("processors", "typesetters.cleaners.handler")
-disableaction("processors", "typesetters.cases.handler")
-disableaction("processors", "typesetters.digits.handler")
-disableaction("processors", "typesetters.breakpoints.handler")
-disableaction("processors", "typesetters.directions.handler")
-disableaction("processors", "languages.words.check")
-disableaction("processors", "typesetters.initials.handler")
-disableaction("processors", "typesetters.firstlines.handler")
-disableaction("processors", "typesetters.spacings.handler")
-disableaction("processors", "typesetters.kerns.handler")
-disableaction("processors", "typesetters.italics.handler")
-disableaction("processors", "languages.visualizediscretionaries")
-disableaction("processors", "nodes.handlers.stripping")
-disableaction("processors", "builders.paragraphs.solutions.splitters.split")
-disableaction("processors", "typesetters.rubies.check")
-disableaction("processors", "typesetters.fontkerns.handler")
-disableaction("processors", "nodes.handlers.flatten")
-disableaction("processors", "typesetters.marksuspects")
-
-disableaction("shipouts", "typesetters.showsuspects")
-disableaction("shipouts", "typesetters.margins.finalhandler")
-disableaction("shipouts", "builders.paragraphs.expansion.trace")
-disableaction("shipouts", "typesetters.alignments.handler")
-disableaction("shipouts", "nodes.rules.handler")
-disableaction("shipouts", "nodes.shifts.handler")
-disableaction("shipouts", "attributes.colors.handler")
-disableaction("shipouts", "attributes.transparencies.handler")
-disableaction("shipouts", "attributes.colorintents.handler")
-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.alignbackgrounds")
-disableaction("shipouts", "nodes.references.handler")
-disableaction("shipouts", "nodes.destinations.handler")
--------------("shipouts", "nodes.handlers.export")
-disableaction("shipouts", "typesetters.rubies.attach")
-
-disableaction("finalizers", "typesetters.margins.localhandler")
-disableaction("finalizers", "builders.paragraphs.keeptogether")
-disableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize")
--------------("finalizers", "nodes.handlers.graphicvadjust") -- sort of obsolete
-disableaction("finalizers", "builders.paragraphs.tag")
-disableaction("finalizers", "nodes.linefillers.handler")
-
-disableaction("contributers","nodes.handlers.flattenline")
-disableaction("contributers","nodes.handlers.textbackgrounds")
-
-disableaction("math", "noads.handlers.showtree")
-disableaction("math", "noads.handlers.tags")
-disableaction("math", "noads.handlers.italics")
-disableaction("math", "noads.handlers.collapse")
-disableaction("math", "noads.handlers.kernpairs")
-disableaction("math", "noads.handlers.domains")
-disableaction("math", "noads.handlers.classes")
-disableaction("math", "noads.handlers.autofences")
-disableaction("math", "noads.handlers.makeup")
-disableaction("math", "typesetters.directions.processmath")
-
-disableaction("mvlbuilders", "typesetters.margins.globalhandler")
-disableaction("mvlbuilders", "nodes.handlers.migrate")
-disableaction("mvlbuilders", "typesetters.checkers.handler")
-disableaction("mvlbuilders", "builders.profiling.pagehandler")
-
--------------("vboxbuilders","typesetters.margins.localhandler")
-disableaction("vboxbuilders","typesetters.checkers.handler")
-disableaction("vboxbuilders","builders.profiling.vboxhandler")
+------------("processors", "before", "nodes.properties.attach", nil, "nut", "enabled" )
+
+appendaction("processors", "normalizers", "typesetters.periodkerns.handler", nil, "nut", "disabled" )
+appendaction("processors", "normalizers", "languages.replacements.handler", nil, "nut", "disabled" )
+appendaction("processors", "normalizers", "typesetters.wrappers.handler", nil, "nut", "disabled" )
+appendaction("processors", "normalizers", "typesetters.characters.handler", nil, "nut", "enabled" )
+appendaction("processors", "normalizers", "fonts.collections.process", nil, "nut", "disabled" )
+appendaction("processors", "normalizers", "fonts.checkers.missing", nil, "nut", "disabled" )
+
+appendaction("processors", "characters", "scripts.autofontfeature.handler", nil, "nut", "disabled" )
+appendaction("processors", "characters", "scripts.splitters.handler", nil, "nut", "disabled" )
+appendaction("processors", "characters", "typesetters.cleaners.handler", nil, "nut", "disabled" )
+appendaction("processors", "characters", "typesetters.directions.handler", nil, "nut", "disabled" )
+appendaction("processors", "characters", "typesetters.cases.handler", nil, "nut", "disabled" )
+appendaction("processors", "characters", "typesetters.breakpoints.handler", nil, "nut", "disabled" )
+appendaction("processors", "characters", "scripts.injectors.handler", nil, "nut", "disabled" )
+
+appendaction("processors", "words", "languages.words.check", nil, "nut", "disabled" )
+appendaction("processors", "words", "languages.hyphenators.handler", nil, "nut", "enabled" )
+appendaction("processors", "words", "typesetters.initials.handler", nil, "nut", "disabled" )
+appendaction("processors", "words", "typesetters.firstlines.handler", nil, "nut", "disabled" )
+
+appendaction("processors", "fonts", "builders.paragraphs.solutions.splitters.split", nil, "nut", "disabled" )
+appendaction("processors", "fonts", "nodes.handlers.characters", nil, "nut", "enabled" )
+appendaction("processors", "fonts", "nodes.injections.handler", nil, "nut", "enabled" )
+appendaction("processors", "fonts", "typesetters.fontkerns.handler", nil, "nut", "disabled" )
+appendaction("processors", "fonts", "nodes.handlers.protectglyphs", nil, "nonut", "enabled" )
+appendaction("processors", "fonts", "builders.kernel.ligaturing", nil, "nut", "disabled" )
+appendaction("processors", "fonts", "builders.kernel.kerning", nil, "nut", "disabled" )
+appendaction("processors", "fonts", "builders.kernel.cleanup", nil, "nut", "enabled" )
+appendaction("processors", "fonts", "nodes.handlers.stripping", nil, "nut", "disabled" )
+appendaction("processors", "fonts", "nodes.handlers.flatten", nil, "nut", "disabled" )
+appendaction("processors", "fonts", "fonts.goodies.colorschemes.coloring", nil, "nut", "disabled" )
+
+appendaction("processors", "lists", "typesetters.rubies.check", nil, "nut", "disabled" )
+appendaction("processors", "lists", "typesetters.characteralign.handler", nil, "nut", "disabled" )
+appendaction("processors", "lists", "typesetters.spacings.handler", nil, "nut", "disabled" )
+appendaction("processors", "lists", "typesetters.kerns.handler", nil, "nut", "disabled" )
+appendaction("processors", "lists", "typesetters.digits.handler", nil, "nut", "disabled" )
+appendaction("processors", "lists", "typesetters.italics.handler", nil, "nut", "disabled" )
+appendaction("processors", "lists", "languages.visualizediscretionaries", nil, "nut", "disabled" )
+
+appendaction("processors", "after", "typesetters.marksuspects", nil, "nut", "disabled" )
+
+appendaction("shipouts", "normalizers", "typesetters.showsuspects", nil, "nut", "disabled" )
+appendaction("shipouts", "normalizers", "typesetters.margins.finalhandler", nil, "nut", "disabled" )
+------------("shipouts", "normalizers", "nodes.handlers.cleanuppage", nil, "nut", "disabled" )
+appendaction("shipouts", "normalizers", "builders.paragraphs.expansion.trace", nil, "nut", "disabled" )
+appendaction("shipouts", "normalizers", "typesetters.alignments.handler", nil, "nut", "disabled" )
+appendaction("shipouts", "normalizers", "nodes.references.handler", nil, "nut", "production")
+appendaction("shipouts", "normalizers", "nodes.destinations.handler", nil, "nut", "production")
+appendaction("shipouts", "normalizers", "nodes.rules.handler", nil, "nut", "disabled" )
+appendaction("shipouts", "normalizers", "nodes.shifts.handler", nil, "nut", "disabled" )
+appendaction("shipouts", "normalizers", "structures.tags.handler", nil, "nut", "disabled" )
+appendaction("shipouts", "normalizers", "nodes.handlers.accessibility", nil, "nut", "disabled" )
+appendaction("shipouts", "normalizers", "nodes.handlers.backgrounds", nil, "nut", "disabled" )
+appendaction("shipouts", "normalizers", "typesetters.rubies.attach", nil, "nut", "disabled" )
+------------("shipouts", "normalizers", "nodes.properties.delayed", nil, "nut", "production")
+
+appendaction("shipouts", "finishers", "nodes.visualizers.handler", nil, "nut", "disabled" )
+appendaction("shipouts", "finishers", "attributes.colors.handler", nil, "nut", "disabled" )
+appendaction("shipouts", "finishers", "attributes.transparencies.handler", nil, "nut", "disabled" )
+appendaction("shipouts", "finishers", "attributes.colorintents.handler", nil, "nut", "disabled" )
+appendaction("shipouts", "finishers", "attributes.negatives.handler", nil, "nut", "disabled" )
+appendaction("shipouts", "finishers", "attributes.effects.handler", nil, "nut", "disabled" )
+appendaction("shipouts", "finishers", "attributes.viewerlayers.handler", nil, "nut", "disabled" )
+
+appendaction("shipouts", "wrapup", "nodes.handlers.export", nil, "nut", "disabled" ) -- always last
+appendaction("shipouts", "wrapup", "luatex.synctex.collect", nil, "nut", "disabled" )
+
+appendaction("math", "normalizers", "noads.handlers.showtree", nil, "nonut", "disabled" )
+appendaction("math", "normalizers", "noads.handlers.unscript", nil, "nonut", "enabled" )
+appendaction("math", "normalizers", "noads.handlers.unstack", nil, "nonut", "disabled" )
+appendaction("math", "normalizers", "noads.handlers.variants", nil, "nonut", "enabled" )
+appendaction("math", "normalizers", "noads.handlers.relocate", nil, "nonut", "enabled" )
+appendaction("math", "normalizers", "noads.handlers.families", nil, "nonut", "enabled" )
+appendaction("math", "normalizers", "noads.handlers.render", nil, "nonut", "enabled" )
+appendaction("math", "normalizers", "noads.handlers.collapse", nil, "nonut", "disabled" )
+appendaction("math", "normalizers", "noads.handlers.fixscripts", nil, "nonut", "enabled" )
+appendaction("math", "normalizers", "noads.handlers.domains", nil, "nonut", "disabled" )
+appendaction("math", "normalizers", "noads.handlers.autofences", nil, "nonut", "disabled" )
+appendaction("math", "normalizers", "noads.handlers.resize", nil, "nonut", "enabled" )
+------------("math", "normalizers", "noads.handlers.respace", nil, "nonut", "enabled" )
+appendaction("math", "normalizers", "noads.handlers.alternates", nil, "nonut", "enabled" )
+appendaction("math", "normalizers", "noads.handlers.tags", nil, "nonut", "disabled" )
+appendaction("math", "normalizers", "noads.handlers.italics", nil, "nonut", "disabled" )
+appendaction("math", "normalizers", "noads.handlers.kernpairs", nil, "nonut", "disabled" )
+appendaction("math", "normalizers", "noads.handlers.classes", nil, "nonut", "disabled" )
+
+appendaction("math", "builders", "builders.kernel.mlist_to_hlist", nil, "nut", "enabled" ) -- mandate
+appendaction("math", "builders", "typesetters.directions.processmath", nil, "nut", "disabled" )
+appendaction("math", "builders", "noads.handlers.makeup", nil, "nonut", "disabled" )
+appendaction("math", "builders", "noads.handlers.align", nil, "nonut", "enabled" )
+
+appendaction("finalizers", "lists", "typesetters.paragraphs.normalize", nil, "nut", "enabled" ) -- "disabled"
+appendaction("finalizers", "lists", "typesetters.margins.localhandler", nil, "nut", "disabled" )
+appendaction("finalizers", "lists", "builders.paragraphs.keeptogether", nil, "nut", "disabled" )
+appendaction("finalizers", "fonts", "builders.paragraphs.solutions.splitters.optimize", nil, "nonut", "disabled" )
+appendaction("finalizers", "lists", "builders.paragraphs.tag", nil, "nut", "disabled" )
+appendaction("finalizers", "lists", "nodes.linefillers.handler", nil, "nut", "disabled" )
+
+appendaction("contributers", "normalizers", "nodes.handlers.flattenline", nil, "nut", "disabled" )
+appendaction("contributers", "normalizers", "nodes.handlers.textbackgrounds", nil, "nut", "disabled" )
+
+appendaction("vboxbuilders", "normalizers", "nodes.handlers.backgroundsvbox", nil, "nut", "disabled" )
+------------("vboxbuilders", "normalizers", "typesetters.margins.localhandler", nil, "nut", "disabled" )
+appendaction("vboxbuilders", "normalizers", "builders.vspacing.vboxhandler", nil, "nut", "enabled" )
+appendaction("vboxbuilders", "normalizers", "builders.profiling.vboxhandler", nil, "nut", "disabled" )
+appendaction("vboxbuilders", "normalizers", "typesetters.checkers.handler", nil, "nut", "disabled" )
+
+appendaction("mvlbuilders", "normalizers", "nodes.handlers.backgroundspage", nil, "nut", "disabled" )
+appendaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler", nil, "nut", "disabled" )
+appendaction("mvlbuilders", "normalizers", "nodes.handlers.migrate", nil, "nut", "disabled" )
+appendaction("mvlbuilders", "normalizers", "builders.vspacing.pagehandler", nil, "nut", "enabled" )
+appendaction("mvlbuilders", "normalizers", "builders.profiling.pagehandler", nil, "nut", "disabled" )
+appendaction("mvlbuilders", "normalizers", "typesetters.checkers.handler", nil, "nut", "disabled" )
+
+appendaction("everypar", "normalizers", "nodes.handlers.checkparcounter", nil, "nut", "disabled" )
+
+-- some protection
freezecallbacks("find_.*_file", "find file using resolver")
freezecallbacks("read_.*_file", "read file at once")
@@ -253,8 +161,12 @@ freezegroup("finalizers", "normalizers")
freezegroup("finalizers", "fonts")
freezegroup("finalizers", "lists")
+freezegroup("math", "normalizers")
+freezegroup("math", "builders")
+
freezegroup("shipouts", "normalizers")
freezegroup("shipouts", "finishers")
+freezegroup("shipouts", "wrapup")
freezegroup("mvlbuilders", "normalizers")
freezegroup("vboxbuilders", "normalizers")
@@ -265,15 +177,14 @@ freezegroup("vboxbuilders", "normalizers")
freezegroup("math", "normalizers")
freezegroup("math", "builders")
--- new: disabled here
+freezegroup("everypar", "normalizers")
-disableaction("processors", "builders.kernel.ligaturing")
-disableaction("processors", "builders.kernel.kerning")
+-- new: disabled here
directives.register("nodes.basepass", function(v)
if v then
- enableaction("processors", "builders.kernel.ligaturing")
- enableaction("processors", "builders.kernel.kerning")
+ enableaction("processors", "builders.kernel.ligaturing")
+ enableaction("processors", "builders.kernel.kerning")
else
disableaction("processors", "builders.kernel.ligaturing")
disableaction("processors", "builders.kernel.kerning")
diff --git a/tex/context/base/mkiv/toks-aux.mkiv b/tex/context/base/mkiv/toks-aux.mkiv
new file mode 100644
index 000000000..5b43de596
--- /dev/null
+++ b/tex/context/base/mkiv/toks-aux.mkiv
@@ -0,0 +1,51 @@
+%D \module
+%D [ file=toks-aux,
+%D version=2018.11.29,
+%D title=\CONTEXT\ Token Support,
+%D subtitle=Helpers,
+%D author=Wolfgang Schuster,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Token Support / Helpers}
+
+\unprotect
+
+\installcorenamespace {tokenlist}
+
+\unexpanded\def\definetokenlist[#1]%
+ {\ifcsname\??tokenlist#1\endcsname
+ \global\lastnamedcs\emptytoks
+ \else
+ \expandafter\newtoks\csname\??tokenlist#1\endcsname
+ \fi}
+
+\unexpanded\def\starttokenlist[#1]#2\stoptokenlist
+ {\ifcsname\??tokenlist#1\endcsname \else
+ \expandafter\newtoks\csname\??tokenlist#1\endcsname
+ \fi
+ \toksapp\lastnamedcs{#2}}
+
+\let\stoptokenlist\relax
+
+\def\gettokenlist[#1]%
+ {\ifcsname\??tokenlist#1\endcsname
+ \the\lastnamedcs
+ \fi}
+
+\def\settokenlist[#1]#2%
+ {\ifcsname\??tokenlist#1\endcsname \else
+ \expandafter\newtoks\csname\??tokenlist#1\endcsname
+ \fi
+ \toksapp\lastnamedcs{#2}}
+
+\unexpanded\def\resettokenlist[#1]%
+ {\ifcsname\??tokenlist#1\endcsname
+ \lastnamedcs\emptytoks
+ \fi}
+
+\protect
diff --git a/tex/context/base/mkiv/toks-ini.lua b/tex/context/base/mkiv/toks-ini.lua
index 15e5df267..43e2d80a3 100644
--- a/tex/context/base/mkiv/toks-ini.lua
+++ b/tex/context/base/mkiv/toks-ini.lua
@@ -18,41 +18,15 @@ local printtable = table.print
local concat = table.concat
local format = string.format
-if setinspector then
+if token.commands then
- local istoken = token.is_token
- local simple = { letter = "letter", other_char = "other" }
+ local commands = token.commands()
- local function astable(t)
- if t and istoken(t) then
- local cmdname = t.cmdname
- local simple = simple[cmdname]
- if simple then
- return {
- category = simple,
- character = utfchar(t.mode) or nil,
- }
- else
- return {
- command = t.command,
- id = t.id,
- tok = t.tok,
- csname = t.csname,
- active = t.active,
- expandable = t.expandable,
- protected = t.protected,
- mode = t.mode,
- index = t.index,
- cmdname = cmdname,
- }
- end
- end
- end
+ tokens.commands = utilities.storage.allocate(table.swapped(commands,commands))
- tokens.istoken = istoken
- tokens.astable = astable
+else
- setinspector("token",function(v) if istoken(v) then printtable(astable(v),tostring(v)) return true end end)
+ tokens.commands = { }
end
@@ -69,6 +43,8 @@ local scan_token = token.scan_token
local scan_word = token.scan_word
local scan_number = token.scan_number
local scan_csname = token.scan_csname
+local scan_real = token.scan_real
+local scan_float = token.scan_float
local get_next = token.get_next
@@ -77,25 +53,26 @@ local get_macro = token.get_macro
local get_meaning = token.get_meaning
local get_cmdname = token.get_cmdname
local set_char = token.set_char
+local set_lua = token.set_lua
+
local create_token = token.create
+local new_token = token.new
+local is_defined = token.is_defined
+local is_token = token.is_token
-if not set_char then -- for a while
- local contextsprint = context.sprint
- local ctxcatcodes = catcodes.numbers.ctxcatcodes
- set_char = function(n,u) contextsprint(ctxcatcodes,format("\\chardef\\%s=%s",n,u)) end
-end
+if not is_defined then
+
+ is_defined = function(name)
+ return get_cmdname(create_token(name)) ~= "undefined_cs"
+ end
-function tokens.defined(name)
- return get_cmdname(create_token(name)) ~= "undefined_cs"
end
--- set_macro = function(k,v,g)
--- if g == "global" then
--- context.setgvalue(k,v or '')
--- else
--- context.setvalue(k,v or '')
--- end
--- end
+tokens.new = new_token
+tokens.create = create_token
+tokens.istoken = is_token
+tokens.isdefined = is_defined
+tokens.defined = is_defined
local bits = {
escape = 0x00000001, -- 2^00
@@ -240,6 +217,8 @@ tokens.scanners = { -- these expand
glue = scan_glue,
skip = scan_glue,
integer = scan_int,
+ real = scan_real,
+ float = scan_float,
count = scan_int,
string = scan_string,
argument = scan_argument,
@@ -268,6 +247,7 @@ tokens.getters = { -- these don't expand
tokens.setters = {
macro = set_macro,
char = set_char,
+ lua = set_lua,
count = tex.setcount,
dimen = tex.setdimen,
skip = tex.setglue,
@@ -297,3 +277,48 @@ tokens.setters = {
-- /* unsave_tex_scanner(texstate); */
-- return 1;
-- }
+
+if setinspector then
+
+ local simple = { letter = "letter", other_char = "other" }
+
+ local function astable(t)
+ if t and is_token(t) then
+ local cmdname = t.cmdname
+ local simple = simple[cmdname]
+ if simple then
+ return {
+ category = simple,
+ character = utfchar(t.mode) or nil,
+ }
+ else
+ return {
+ command = t.command,
+ id = t.id,
+ tok = t.tok,
+ csname = t.csname,
+ active = t.active,
+ expandable = t.expandable,
+ protected = t.protected,
+ mode = t.mode,
+ index = t.index,
+ cmdname = cmdname,
+ }
+ end
+ end
+ end
+
+ tokens.astable = astable
+
+ setinspector("token",function(v) local t = astable(v) if t then printtable(t,tostring(v)) return true end end)
+
+end
+
+tokens.cache = table.setmetatableindex(function(t,k)
+ if not is_defined(k) then
+ set_macro(k,"","global")
+ end
+ local v = create_token(k)
+ t[k] = v
+ return v
+end)
diff --git a/tex/context/base/mkiv/toks-ini.mkiv b/tex/context/base/mkiv/toks-ini.mkiv
index 9d3375432..af22d5393 100644
--- a/tex/context/base/mkiv/toks-ini.mkiv
+++ b/tex/context/base/mkiv/toks-ini.mkiv
@@ -15,11 +15,6 @@
\unprotect
-\newtoks\t_get_macro % will go away
-
\registerctxluafile{toks-ini}{}
-\registerctxluafile{toks-scn}{}
-\registerctxluafile{cldf-scn}{}
-\registerctxluafile{cldf-stp}{}
\protect \endinput
diff --git a/tex/context/base/mkiv/toks-scn.lua b/tex/context/base/mkiv/toks-scn.lua
index fe32a1de4..f73ecc86c 100644
--- a/tex/context/base/mkiv/toks-scn.lua
+++ b/tex/context/base/mkiv/toks-scn.lua
@@ -106,7 +106,40 @@ local function scanconditional()
return nil
end
+local function scantable(t,data)
+ if not data then
+ data = { }
+ end
+ local wrapped = scanopen()
+ while true do
+ local key = scanword()
+ if key then
+ local get = t[key]
+ if get then
+ data[key] = get()
+ else
+ -- catch all we can get
+ end
+ else
+ break
+ end
+ end
+ if wrapped then
+ scanclose()
+ end
+ return data
+end
+
+function tokens.constant(s)
+ if type(s) == "string" then
+ return "'" .. s .. "'"
+ else
+ return s
+ end
+end
+
scanners.list = scanlist
+scanners.table = scantable
scanners.conditional = scanconditional
local shortcuts = {
@@ -118,6 +151,7 @@ local shortcuts = {
scanstring = scanstring,
scaninteger = scaninteger,
scannumber = scannumber,
+ scantable = scantable,
scankeyword = scankeyword,
scankeywordcs = scankeywordcs,
scanword = scanword,
@@ -254,6 +288,8 @@ local presets = {
["8 strings"] = { "string", "string", "string", "string", "string", "string", "string", "string" },
}
+tokens.presets = presets
+
function tokens.compile(specification)
local f = { }
local n = 0
@@ -319,7 +355,7 @@ function tokens.compile(specification)
return c
end
end
- local p = t and presets[t]
+ local p = t and presets[t] -- already done in implement
if p then
t = p
end
@@ -460,35 +496,3 @@ end
-- }
--
-- os.exit()
-
-function tokens.scantable(t,data)
- if not data then
- data = { }
- end
- local wrapped = scanopen()
- while true do
- local key = scanword()
- if key then
- local get = t[key]
- if get then
- data[key] = get()
- else
- -- catch all we can get
- end
- else
- break
- end
- end
- if wrapped then
- scanclose()
- end
- return data
-end
-
-function tokens.constant(s)
- if type(s) == "string" then
- return "'" .. s .. "'"
- else
- return s
- end
-end
diff --git a/tex/context/base/mkiv/toks-scn.mkiv b/tex/context/base/mkiv/toks-scn.mkiv
new file mode 100644
index 000000000..49edf0c24
--- /dev/null
+++ b/tex/context/base/mkiv/toks-scn.mkiv
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=toks-ini,
+%D version=2007.03.03,
+%D title=\CONTEXT\ Token Support,
+%D subtitle=Initialization,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Token Support / Scanners}
+
+\unprotect
+
+\registerctxluafile{toks-scn}{}
+\registerctxluafile{cldf-scn}{}
+\registerctxluafile{cldf-stp}{}
+
+\protect \endinput
diff --git a/tex/context/base/mkiv/trac-deb.lua b/tex/context/base/mkiv/trac-deb.lua
index 03df86825..95f3052fe 100644
--- a/tex/context/base/mkiv/trac-deb.lua
+++ b/tex/context/base/mkiv/trac-deb.lua
@@ -220,7 +220,13 @@ function tracers.printerror(specification)
else
report_nl()
if luaerrorline then
- report("lua error on line %s in file %s:\n\n%s",linenumber,filename,lastluaerror)
+ if linenumber == 0 or not filename or filename == "" then
+ print("\nfatal lua error:\n\n",lastluaerror,"\n")
+ os.exit(1)
+ return
+ else
+ report("lua error on line %s in file %s:\n\n%s",linenumber,filename,lastluaerror)
+ end
elseif lastmpserror then
report("mp error on line %s in file %s:\n\n%s",linenumber,filename,lastmpserror)
else
@@ -341,22 +347,25 @@ directives.register("system.showerror", lmx.overloaderror)
-- trace_calls(n)
-- end) -- indirect is needed for nilling
-local editor = [[scite "-open:%filename%" -goto:%linenumber%]]
-
-directives.register("system.editor",function(v)
- editor = v
-end)
+-- Obsolete ... not that usefull as normally one runs from an editor and
+-- when run unattended it makes no sense either.
-callback.register("call_edit",function(filename,linenumber)
- if editor then
- editor = gsub(editor,"%%s",filename)
- editor = gsub(editor,"%%d",linenumber)
- editor = gsub(editor,"%%filename%%",filename)
- editor = gsub(editor,"%%linenumber%%",linenumber)
- logs.report("system","starting editor: %s",editor)
- os.execute(editor)
- end
-end)
+-- local editor = [[scite "-open:%filename%" -goto:%linenumber%]]
+--
+-- directives.register("system.editor",function(v)
+-- editor = v
+-- end)
+--
+-- callback.register("call_edit",function(filename,linenumber)
+-- if editor then
+-- editor = gsub(editor,"%%s",filename)
+-- editor = gsub(editor,"%%d",linenumber)
+-- editor = gsub(editor,"%%filename%%",filename)
+-- editor = gsub(editor,"%%linenumber%%",linenumber)
+-- logs.report("system","starting editor: %s",editor)
+-- os.execute(editor)
+-- end
+-- end)
implement { name = "showtrackers", actions = trackers.show }
implement { name = "enabletrackers", actions = trackers.enable, arguments = "string" }
diff --git a/tex/context/base/mkiv/trac-inf.lua b/tex/context/base/mkiv/trac-inf.lua
index 439e8b2dc..7a5c35fd5 100644
--- a/tex/context/base/mkiv/trac-inf.lua
+++ b/tex/context/base/mkiv/trac-inf.lua
@@ -82,9 +82,13 @@ local seconds = function(n) return n or 0 end
--
-- end
-local function starttiming(instance)
+local function starttiming(instance,reset)
local timer = timers[instance or "notimer"]
local it = timer.timing
+ if reset then
+ it = 0
+ timer.loadtime = 0
+ end
if it == 0 then
timer.starttime = ticks()
if not timer.loadtime then
@@ -123,6 +127,24 @@ local function elapsed(instance)
end
end
+local function currenttime(instance)
+ if type(instance) == "number" then
+ return instance
+ else
+ local timer = timers[instance or "notimer"]
+ local it = timer.timing
+ if it > 1 then
+ -- whatever
+ else
+ local starttime = timer.starttime
+ if starttime and starttime > 0 then
+ return seconds(timer.loadtime + ticks() - starttime)
+ end
+ end
+ return 0
+ end
+end
+
local function elapsedtime(instance)
return format("%0.3f",elapsed(instance))
end
@@ -141,6 +163,7 @@ statistics.hastiming = hastiming
statistics.resettiming = resettiming
statistics.starttiming = starttiming
statistics.stoptiming = stoptiming
+statistics.currenttime = currenttime
statistics.elapsed = elapsed
statistics.elapsedtime = elapsedtime
statistics.elapsedindeed = elapsedindeed
@@ -229,17 +252,26 @@ end
function statistics.runtime()
stoptiming(statistics)
- -- stoptiming(statistics) -- somehow we can start the timer twice, but where
- return statistics.formatruntime(elapsedtime(statistics))
+ -- stoptiming(statistics) -- somehow we can start the timer twice, but where
+ local runtime = lua.getruntime and lua.getruntime() or elapsedtime(statistics)
+ return statistics.formatruntime(runtime)
end
local report = logs.reporter("system")
-function statistics.timed(action)
+function statistics.timed(action,all)
starttiming("run")
action()
stoptiming("run")
- report("total runtime: %s seconds",elapsedtime("run"))
+ local runtime = tonumber(elapsedtime("run"))
+ if all then
+ local alltime = tonumber(lua.getruntime and lua.getruntime() or elapsedtime(statistics))
+ if alltime and alltime > 0 then
+ report("total runtime: %0.3f seconds of %0.3f seconds",runtime,alltime)
+ return
+ end
+ end
+ report("total runtime: %0.3f seconds",runtime)
end
-- goodie
diff --git a/tex/context/base/mkiv/trac-jus.lua b/tex/context/base/mkiv/trac-jus.lua
index e7a030257..aec1844ec 100644
--- a/tex/context/base/mkiv/trac-jus.lua
+++ b/tex/context/base/mkiv/trac-jus.lua
@@ -15,7 +15,6 @@ local a_alignstate = attributes.private("alignstate")
local a_justification = attributes.private("justification")
local nuts = nodes.nuts
-local tonut = nuts.tonut
local getfield = nuts.getfield
local getlist = nuts.getlist
@@ -26,8 +25,9 @@ local setlink = nuts.setlink
local getwidth = nuts.getwidth
local findtail = nuts.tail
-local traverse_id = nuts.traverse_id
-local list_dimensions = nuts.dimensions
+local nexthlist = nuts.traversers.hlist
+
+local getdimensions = nuts.dimensions
local copy_list = nuts.copy_list
local tracedrule = nodes.tracers.pool.nuts.rule
@@ -77,14 +77,14 @@ trackers.register("visualizers.justification", function(v)
end)
function checkers.handler(head)
- for current in traverse_id(hlist_code,tonut(head)) do
+ for current in nexthlist, head do
if getattr(current,a_justification) == 1 then
setattr(current,a_justification,0) -- kind of reset
local width = getwidth(current)
if width > 0 then
local list = getlist(current)
if list then
- local naturalwidth, naturalheight, naturaldepth = list_dimensions(list)
+ local naturalwidth, naturalheight, naturaldepth = getdimensions(list)
local delta = naturalwidth - width
if naturalwidth == 0 or delta == 0 then
-- special box
diff --git a/tex/context/base/mkiv/trac-log.lua b/tex/context/base/mkiv/trac-log.lua
index 1471bd4c7..206af5668 100644
--- a/tex/context/base/mkiv/trac-log.lua
+++ b/tex/context/base/mkiv/trac-log.lua
@@ -405,6 +405,15 @@ if runningtex then
setlogfile = ignore
settimedlog = ignore
+ -- settimedlog = function()
+ -- local localtime = os.localtime
+ -- local writeline = write_nl
+ -- write_nl = function(f,...)
+ -- writeline(f,localtime() .. " | " .. concat { ... })
+ -- end
+ -- settimedlog = ignore
+ -- end
+
else
local report_yes, subreport_yes, status_yes
@@ -758,7 +767,7 @@ if tex then
local report = logs.reporter("pages") -- not needed but saves checking when we grep for it
local texgetcount = tex and tex.getcount
- local real, user, sub
+ local real, user, sub = 0, 0, 0
function logs.start_page_number()
real = texgetcount("realpageno")
@@ -766,47 +775,35 @@ if tex then
sub = texgetcount("subpageno")
end
- local timing = false
- local starttime = nil
- local lasttime = nil
+ local timing = false
+ local lasttime = nil
trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
- starttime = os.clock() -- todo: use other timer
- timing = true
+ timing = ""
end)
function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
if timing then
- local elapsed, average
- local stoptime = os.clock()
+ local elapsed = statistics.currenttime(statistics)
+ local average, page
if not lasttime or real < 2 then
- elapsed = stoptime
- average = stoptime
- starttime = stoptime
- else
- elapsed = stoptime - lasttime
- average = (stoptime - starttime) / (real - 1)
- end
- lasttime = stoptime
- if real <= 0 then
- report("flushing page, time %0.04f / %0.04f",elapsed,average)
- elseif user <= 0 then
- report("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
- elseif sub <= 0 then
- report("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ average = elapsed
+ page = elapsed
else
- report("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ average = elapsed / (real - 1)
+ page = elapsed - lasttime
end
+ lasttime = elapsed
+ timing = formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average)
+ end
+ if real <= 0 then
+ report("flushing page%s",timing)
+ elseif user <= 0 then
+ report("flushing realpage %s%s",real,timing)
+ elseif sub <= 0 then
+ report("flushing realpage %s, userpage %s%s",real,user,timing)
else
- if real <= 0 then
- report("flushing page")
- elseif user <= 0 then
- report("flushing realpage %s",real)
- elseif sub <= 0 then
- report("flushing realpage %s, userpage %s",real,user)
- else
- report("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
- end
+ report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing)
end
logs.flush()
end
@@ -1031,7 +1028,7 @@ end
if tex and tex.error then
function logs.texerrormessage(...) -- for the moment we put this function here
- tex.error(format(...), { })
+ tex.error(format(...))
end
else
function logs.texerrormessage(...)
diff --git a/tex/context/base/mkiv/trac-par.lua b/tex/context/base/mkiv/trac-par.lua
index 56291f8c8..03f0a67d1 100644
--- a/tex/context/base/mkiv/trac-par.lua
+++ b/tex/context/base/mkiv/trac-par.lua
@@ -15,13 +15,13 @@ local concat = table.concat
local nuts = nodes.nuts
local tonut = nuts.tonut
-local getfield = nuts.getfield
local getid = nuts.getid
local getnext = nuts.getnext
local getlist = nuts.getlist
-local getfont = nuts.getfont
-local getchar = nuts.getchar
local getwidth = nuts.getwidth
+local getexpansion = nuts.getexpansion
+
+local isglyph = nuts.isglyph
local nodecodes = nodes.nodecodes
local hlist_code = nodecodes.hlist
@@ -63,23 +63,23 @@ local function colorize(n)
-- tricky: the built-in method creates dummy fonts and the last line normally has the
-- original font and that one then has ex.auto set
while n do
- local id = getid(n)
- if id == glyph_code then
- local ne = getfield(n,"expansion_factor")
+ local char, id = isglyph(n)
+ if char then
+ local ne = getexpansion(n)
if ne == 0 then
if length > 0 then flush() end
setnodecolor(n,"hz:zero")
else
- local f = getfont(n)
- if f ~= font then
+ -- id == font
+ if id ~= font then
if length > 0 then
flush()
end
- local pf = parameters[f]
+ local pf = parameters[id]
local ex = pf.expansion
if ex and ex.auto then
size = pf.size
- font = f -- save lookups
+ font = id -- save lookups
else
size = false
end
@@ -100,7 +100,7 @@ local function colorize(n)
end
if trace_verbose then
length = length + 1
- list[length] = utfchar(getchar(n))
+ list[length] = utfchar(char)
width = width + getwidth(n) -- no kerning yet
end
end
@@ -109,7 +109,10 @@ local function colorize(n)
if length > 0 then
flush()
end
- colorize(getlist(n),flush)
+ local list = getlist(n)
+ if list then
+ colorize(list,flush)
+ end
else -- nothing to show on kerns
if length > 0 then
flush()
@@ -125,7 +128,7 @@ end
builders.paragraphs.expansion = builders.paragraphs.expansion or { }
function builders.paragraphs.expansion.trace(head)
- colorize(tonut(head),true)
+ colorize(head,true)
return head
end
diff --git a/tex/context/base/mkiv/trac-set.lua b/tex/context/base/mkiv/trac-set.lua
index 530915fe0..6311d6382 100644
--- a/tex/context/base/mkiv/trac-set.lua
+++ b/tex/context/base/mkiv/trac-set.lua
@@ -396,3 +396,20 @@ if texconfig then
directives.register("luatex.stacksize", function(v) set("stack_size",v) end)
end
+
+-- for now here:
+
+local data = table.setmetatableindex("table")
+
+updaters = {
+ register = function(what,f)
+ local d = data[what]
+ d[#d+1] = f
+ end,
+ apply = function(what,...)
+ local d = data[what]
+ for i=1,#d do
+ d[i](...)
+ end
+ end,
+}
diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua
index 0e37752db..b61dadb51 100644
--- a/tex/context/base/mkiv/trac-vis.lua
+++ b/tex/context/base/mkiv/trac-vis.lua
@@ -28,8 +28,6 @@ local compactfloat = number.compactfloat
-- todo: inline concat (more efficient)
-- todo: tags can also be numbers (just add to hash)
--- todo: dir and localpar nodes
-
local nodecodes = nodes.nodecodes
local nuts = nodes.nuts
@@ -47,12 +45,10 @@ local setattr = nuts.setattr
local setwidth = nuts.setwidth
local setshift = nuts.setshift
-local getfield = nuts.getfield
local getid = nuts.getid
local getfont = nuts.getfont
local getattr = nuts.getattr
local getsubtype = nuts.getsubtype
-local getchar = nuts.getchar
local getbox = nuts.getbox
local getlist = nuts.getlist
local getleader = nuts.getleader
@@ -63,22 +59,26 @@ local getdisc = nuts.getdisc
local getwhd = nuts.getwhd
local getkern = nuts.getkern
local getpenalty = nuts.getpenalty
-local getdir = nuts.getdir
local getwidth = nuts.getwidth
local getdepth = nuts.getdepth
local getshift = nuts.getshift
+local getexpansion = nuts.getexpansion
+
+local isglyph = nuts.isglyph
local hpack_nodes = nuts.hpack
local vpack_nodes = nuts.vpack
local copy_list = nuts.copy_list
+local copy_node = nuts.copy_node
local flush_node_list = nuts.flush_list
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
-local traverse_nodes = nuts.traverse
local apply_to_nodes = nuts.apply
local find_tail = nuts.tail
local effectiveglue = nuts.effective_glue
+local nextnode = nuts.traversers.node
+
local hpack_string = nuts.typesetters.tohpack
local texgetattribute = tex.getattribute
@@ -188,13 +188,16 @@ end
-- we can preset a bunch of bits
-local userrule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule")
+local userrule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule")
+local outlinerule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule")
-local function enable()
+local function initialize()
+ --
if not usedfont then
-- we use a narrow monospaced font -- infofont ?
visualizers.setfont(fonts.definers.define { name = "lmmonoltcond10regular", size = tex.sp("4pt") })
end
+ --
for mode, value in next, modes do
local tag = formatters["v_%s"](mode)
attributes.viewerlayers.define {
@@ -225,14 +228,25 @@ local function enable()
l_line = layers.line
l_space = layers.space
l_depth = layers.depth
- enableaction("shipouts","nodes.visualizers.handler")
- report_visualize("enabled")
- enabled = true
- tex.setcount("global","c_syst_visualizers_state",1) -- so that we can optimize at the tex end
--
if not userrule then
userrule = nuts.rules.userrule
end
+ --
+ if not outlinerule then
+ outlinerule = nuts.pool.outlinerule
+ end
+ initialize = false
+end
+
+local function enable()
+ if initialize then
+ initialize()
+ end
+ enableaction("shipouts","nodes.visualizers.handler")
+ report_visualize("enabled")
+ enabled = true
+ tex.setcount("global","c_syst_visualizers_state",1) -- so that we can optimize at the tex end
end
local function setvisual(n,a,what,list) -- this will become more efficient when we have the bit lib linked in
@@ -454,7 +468,7 @@ local fontkern, italickern do
local function somekern(head,current,cache,color,layer)
local width = getkern(current)
- local extra = getfield(current,"expansion_factor")
+ local extra = getexpansion(current)
local kern = width + extra
local info = cache[kern]
if not info then
@@ -495,7 +509,7 @@ local glyphexpansion do
local f_cache = caches["glyphexpansion"]
glyphexpansion = function(head,current)
- local extra = getfield(current,"expansion_factor")
+ local extra = getexpansion(current)
if extra ~= 0 then
extra = extra / 1000
local info = f_cache[extra]
@@ -529,7 +543,7 @@ local kernexpansion do
local f_cache = caches["kernexpansion"]
kernexpansion = function(head,current)
- local extra = getfield(current,"expansion_factor")
+ local extra = getexpansion(current)
if extra ~= 0 then
extra = extra / 1000
local info = f_cache[extra]
@@ -564,29 +578,17 @@ local whatsit do
local w_cache = caches["whatsit"]
local tags = {
- open = "FIC",
- write = "FIW",
- close = "FIC",
- special = "SPE",
- latelua = "LUA",
- savepos = "POS",
- userdefined = "USR",
- -- backend stuff
- pdfliteral = "PDF",
- pdfrefobj = "PDF",
- pdfannot = "PDF",
- pdfstartlink = "PDF",
- pdfendlink = "PDF",
- pdfdest = "PDF",
- pdfthread = "PDF",
- pdfstartthread = "PDF",
- pdfendthread = "PDF",
- pdfthreaddata = "PDF",
- pdflinkdata = "PDF",
- pdfcolorstack = "PDF",
- pdfsetmatrix = "PDF",
- pdfsave = "PDF",
- pdfrestore = "PDF",
+ open = "OPN",
+ write = "WRI",
+ close = "CLS",
+ special = "SPE",
+ latelua = "LUA",
+ savepos = "POS",
+ userdefined = "USR",
+ literal = "LIT",
+ setmatrix = "MAT",
+ save = "SAV",
+ restore = "RES",
}
whatsit = function(head,current)
@@ -700,40 +702,11 @@ local ruledbox do
local wd, ht, dp = getwhd(current)
if wd ~= 0 then
local shift = getshift(current)
- local dir = getdir(current)
- -- if dir == "LTL" or dir == "RRT" then
- -- wd, ht, dp = ht + dp, wd, 0
- -- end
local next = getnext(current)
local prev = previous
- -- local prev = getprev(current) -- prev can be wrong in math mode < 0.78.3
setboth(current)
local linewidth = emwidth/fraction
local size = 2*linewidth
- -- local baseline, baseskip
- -- if dp ~= 0 and ht ~= 0 then
- -- if wd > 20*linewidth then
- -- local targetsize = wd - size
- -- baseline = b_cache[targetsize]
- -- 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 = setlink(new_glue(size),new_rule(3*size,linewidth,0),new_glue(size))
- -- leader = hpack_nodes(leader)
- -- baseline = new_glue(0,65536,0,2,0)
- -- setleader(baseline,leader)
- -- setsubtype(baseline,cleaders_code)
- -- setlisttransparency(baseline,c_text)
- -- baseline = hpack_nodes(baseline,targetsize)
- -- b_cache[targetsize] = baseline
- -- end
- -- baseline = copy_list(baseline)
- -- baseskip = new_kern(-wd+linewidth)
- -- else
- -- baseline = new_rule(wd-size,linewidth,0)
- -- baseskip = new_kern(-wd+size)
- -- end
- -- end
local this
if not simple then
this = b_cache[what]
@@ -746,22 +719,9 @@ local ruledbox do
end
end
-- we need to trigger the right mode (else sometimes no whatits)
- -- local info = setlink(
- -- this and copy_list(this) or nil,
- -- new_rule(linewidth,ht,dp),
- -- new_rule(wd-size,-dp+linewidth,dp),
- -- new_rule(linewidth,ht,dp),
- -- new_kern(-wd+linewidth),
- -- new_rule(wd-size,ht,-ht+linewidth),
- -- baseskip,
- -- baseskip and baseline or nil
- -- )
- --
- -- userrules:
- --
local info = setlink(
this and copy_list(this) or nil,
- userrule {
+ (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule {
width = wd,
height = ht,
depth = dp,
@@ -772,7 +732,7 @@ local ruledbox do
)
--
setlisttransparency(info,c_text)
- info = new_hlist(info)
+ info = new_hlist(info) -- important
--
setattr(info,a_layer,layer)
if vertical then
@@ -846,56 +806,16 @@ local ruledglyph do
ruledglyph = function(head,current,previous) -- wrong for vertical glyphs
local wd = getwidth(current)
- -- local wd = chardata[getfont(current)][getchar(current)].width
if wd ~= 0 then
local wd, ht, dp = getwhd(current)
- -- local dir = getdir(current)
- -- if dir == "LTL" or dir = "RTT" then
- -- wd, ht, dp = ht + dp, wd, 0
- -- end
local next = getnext(current)
local prev = previous
setboth(current)
local linewidth = emwidth/(2*fraction)
local info
--
- -- original
- --
- -- local baseline
- -- if (dp >= 0 and ht >= 0) or (dp <= 0 and ht <= 0) then
- -- baseline = new_rule(wd-2*linewidth,linewidth,0)
- -- end
- -- local doublelinewidth = 2*linewidth
- -- -- could be a pdf rule (or a user rule now)
- -- info = setlink(
- -- 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
- -- )
- --
- -- experiment with subtype outline
- --
- -- if (dp >= 0 and ht >= 0) or (dp <= 0 and ht <= 0) then
- -- baseline = new_rule(wd,linewidth/2,0)
- -- end
- -- local r = new_rule(wd-linewidth,ht-linewidth/4,dp-linewidth/4)
- -- setsubtype(r,nodes.rulecodes.outline)
- -- setfield(r,"transform",linewidth)
- -- info = setlink(
- -- new_kern(linewidth/4),
- -- r,
- -- new_kern(-wd+linewidth/2),
- -- baseline
- -- )
- --
- -- userrules:
- --
info = setlink(
- userrule {
+ (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule {
width = wd,
height = ht,
depth = dp,
@@ -905,7 +825,8 @@ local ruledglyph do
new_kern(-wd)
)
--
- local char = chardata[getfont(current)][getchar(current)]
+ local c, f = isglyph(current)
+ local char = chardata[f][c]
if char and type(char.unicode) == "table" then -- hackery test
setlistcolor(info,c_ligature)
setlisttransparency(info,c_ligature_d)
@@ -942,19 +863,22 @@ end
local ruledglue do
- local gluecodes = nodes.gluecodes
- local cleaders_code = gluecodes.cleaders
- local userskip_code = gluecodes.userskip
- local space_code = gluecodes.spaceskip
- local xspace_code = gluecodes.xspaceskip
- local leftskip_code = gluecodes.leftskip
- local rightskip_code = gluecodes.rightskip
+ local gluecodes = nodes.gluecodes
+ local leadercodes = nodes.gluecodes
+
+ local userskip_code = gluecodes.userskip
+ local spaceskip_code = gluecodes.spaceskip
+ local xspaceskip_code = gluecodes.xspaceskip
+ local leftskip_code = gluecodes.leftskip
+ local rightskip_code = gluecodes.rightskip
+
+ local cleaders_code = leadercodes.cleaders
local g_cache_v = caches["vglue"]
local g_cache_h = caches["hglue"]
local tags = {
- -- userskip = "US",
+ -- [gluecodes.userskip] = "US",
[gluecodes.lineskip] = "LS",
[gluecodes.baselineskip] = "BS",
[gluecodes.parskip] = "PS",
@@ -973,12 +897,12 @@ local ruledglue do
[gluecodes.thinmuskip] = "MS",
[gluecodes.medmuskip] = "MM",
[gluecodes.thickmuskip] = "ML",
- [gluecodes.leaders] = "NL",
- [gluecodes.cleaders] = "CL",
- [gluecodes.xleaders] = "XL",
- [gluecodes.gleaders] = "GL",
- -- true = "VS",
- -- false = "HS",
+ [leadercodes.leaders] = "NL",
+ [leadercodes.cleaders] = "CL",
+ [leadercodes.xleaders] = "XL",
+ [leadercodes.gleaders] = "GL",
+ -- true = "VS",
+ -- false = "HS",
}
-- we sometimes pass previous as we can have issues in math (not watertight for all)
@@ -991,7 +915,7 @@ local ruledglue do
if info then
-- print("glue hit")
else
- if subtype == space_code or subtype == xspace_code then
+ if subtype == spaceskip_code or subtype == xspaceskip_code then
info = sometext(amount,l_glue,c_space)
elseif subtype == leftskip_code or subtype == rightskip_code then
info = sometext(amount,l_glue,c_skip_a)
@@ -1018,7 +942,7 @@ local ruledglue do
-- ruledspace = function(head,current,parent)
-- local subtype = getsubtype(current)
- -- if subtype == space_code or subtype == xspace_code then
+ -- if subtype == spaceskip_code or subtype == xspaceskip_code then
-- local width = effectiveglue(current,parent)
-- local amount = formatters["%s:%0.3f"](tags[subtype] or "HS",width*pt_factor)
-- local info = g_cache_h[amount]
@@ -1041,10 +965,10 @@ local ruledglue do
ruledspace = function(head,current,parent)
local subtype = getsubtype(current)
- if subtype == space_code or subtype == xspace_code then -- not yet all space
+ if subtype == spaceskip_code or subtype == xspaceskip_code then -- not yet all space
local width = effectiveglue(current,parent)
local info
- if subtype == space_code then
+ if subtype == spaceskip_code then
info = g_cache_s[width]
if not info then
info = someblob("SP",l_glue,c_space,nil,width)
@@ -1179,24 +1103,26 @@ end
do
- local disc_code = nodecodes.disc
- local kern_code = nodecodes.kern
- local glyph_code = nodecodes.glyph
- local glue_code = nodecodes.glue
- local penalty_code = nodecodes.penalty
- local whatsit_code = nodecodes.whatsit
- local user_code = nodecodes.user
- local math_code = nodecodes.math
- local hlist_code = nodecodes.hlist
- local vlist_code = nodecodes.vlist
-
- local kerncodes = nodes.kerncodes
- local font_kern_code = kerncodes.fontkern
- local italic_kern_code = kerncodes.italiccorrection
- ----- user_kern_code = kerncodes.userkern
-
- local listcodes = nodes.listcodes
- local line_code = listcodes.line
+ local disc_code = nodecodes.disc
+ local kern_code = nodecodes.kern
+ local glyph_code = nodecodes.glyph
+ local glue_code = nodecodes.glue
+ local penalty_code = nodecodes.penalty
+ local whatsit_code = nodecodes.whatsit
+ local user_code = nodecodes.user
+ local math_code = nodecodes.math
+ local hlist_code = nodecodes.hlist
+ local vlist_code = nodecodes.vlist
+
+ local kerncodes = nodes.kerncodes
+ local fontkern_code = kerncodes.fontkern
+ local italickern_code = kerncodes.italiccorrection
+ ----- userkern_code = kerncodes.userkern
+
+ local listcodes = nodes.listcodes
+ local linelist_code = listcodes.line
+
+ local cache
local function visualize(head,vertical,forced,parent)
local trace_hbox = false
@@ -1225,6 +1151,58 @@ do
local prev_trace_fontkern = nil
local prev_trace_italic = nil
local prev_trace_expansion = nil
+
+ -- local function setthem(t,k)
+ -- local v_trace_hbox = band(k, 1) ~= 0
+ -- local v_trace_vbox = band(k, 2) ~= 0
+ -- local v_trace_vtop = band(k, 4) ~= 0
+ -- local v_trace_kern = band(k, 8) ~= 0
+ -- local v_trace_glue = band(k, 16) ~= 0
+ -- local v_trace_penalty = band(k, 32) ~= 0
+ -- local v_trace_fontkern = band(k, 64) ~= 0
+ -- local v_trace_strut = band(k, 128) ~= 0
+ -- local v_trace_whatsit = band(k, 256) ~= 0
+ -- local v_trace_glyph = band(k, 512) ~= 0
+ -- local v_trace_simple = band(k, 1024) ~= 0
+ -- local v_trace_user = band(k, 2048) ~= 0
+ -- local v_trace_math = band(k, 4096) ~= 0
+ -- local v_trace_italic = band(k, 8192) ~= 0
+ -- local v_trace_origin = band(k, 16384) ~= 0
+ -- local v_trace_discretionary = band(k, 32768) ~= 0
+ -- local v_trace_expansion = band(k, 65536) ~= 0
+ -- local v_trace_line = band(k,131072) ~= 0
+ -- local v_trace_space = band(k,262144) ~= 0
+ -- local v_trace_depth = band(k,524288) ~= 0
+ -- local v = function()
+ -- trace_hbox = v_trace_hbox
+ -- trace_vbox = v_trace_vbox
+ -- trace_vtop = v_trace_vtop
+ -- trace_kern = v_trace_kern
+ -- trace_glue = v_trace_glue
+ -- trace_penalty = v_trace_penalty
+ -- trace_fontkern = v_trace_fontkern
+ -- trace_strut = v_trace_strut
+ -- trace_whatsit = v_trace_whatsit
+ -- trace_glyph = v_trace_glyph
+ -- trace_simple = v_trace_simple
+ -- trace_user = v_trace_user
+ -- trace_math = v_trace_math
+ -- trace_italic = v_trace_italic
+ -- trace_origin = v_trace_origin
+ -- trace_discretionary = v_trace_discretionary
+ -- trace_expansion = v_trace_expansion
+ -- trace_line = v_trace_line
+ -- trace_space = v_trace_space
+ -- trace_depth = v_trace_depth
+ -- end
+ -- t[k] = v
+ -- return v
+ -- end
+ --
+ -- if not cache then
+ -- cache = setmetatableindex(setthem)
+ -- end
+
while current do
local id = getid(current)
local a = forced or getattr(current,a_visual) or unsetvalue
@@ -1254,6 +1232,7 @@ do
trace_space = false
trace_depth = false
else -- dead slow:
+ -- cache[a]()
trace_hbox = band(a, 1) ~= 0
trace_vbox = band(a, 2) ~= 0
trace_vtop = band(a, 4) ~= 0
@@ -1303,14 +1282,14 @@ do
setdisc(current,pre,post,replace)
elseif id == kern_code then
local subtype = getsubtype(current)
- if subtype == font_kern_code then
+ if subtype == fontkern_code then
if trace_fontkern or prev_trace_fontkern then
head, current = fontkern(head,current)
end
if trace_expansion or prev_trace_expansion then
head, current = kernexpansion(head,current)
end
- elseif subtype == italic_kern_code then
+ elseif subtype == italickern_code then
if trace_italic or prev_trace_italic then
head, current = italickern(head,current)
elseif trace_kern then
@@ -1342,7 +1321,7 @@ do
if trace_depth then
ruleddepth(current)
end
- if trace_line and getsubtype(current) == line_code then
+ if trace_line and getsubtype(current) == linelist_code then
head, current = ruledbox(head,current,false,l_line,"L__",trace_simple,previous,trace_origin,parent)
elseif trace_hbox then
head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous,trace_origin,parent)
@@ -1390,9 +1369,9 @@ do
local function handler(head)
if usedfont then
starttiming(visualizers)
- head = visualize(tonut(head),true)
+ head = visualize(head,true)
stoptiming(visualizers)
- return tonode(head), true
+ return head, true
else
return head, false
end
@@ -1433,8 +1412,7 @@ do
}
local function markfonts(list)
- for n in traverse_nodes(list) do
- local id = getid(n)
+ for n, id in nextnode, list do
if id == glyph_code then
local font = getfont(n)
local okay = used[font]
@@ -1507,3 +1485,57 @@ do
}
end
+
+-- Here for now:
+
+do
+
+ local function make(str,forecolor,rulecolor,layer)
+ if initialize then
+ initialize()
+ end
+ local rule = new_rule(emwidth/fraction,exheight,4*exheight)
+ setcolor(rule,rulecolor)
+ settransparency(rule,rulecolor)
+ local info
+ if str == "" then
+ info = new_hlist(rule)
+ else
+ local text = hpack_string(str,usedfont)
+ local list = getlist(text)
+ setlistcolor(list,textcolor)
+ setlisttransparency(list,textcolor)
+ setshift(text,3.5 * exheight)
+ info = new_hlist(setlink(rule,text))
+ end
+ setattr(info,a_layer,layer)
+ return info
+ end
+
+ function visualizers.register(name,textcolor,rulecolor)
+ if rawget(layers,name) then
+ -- message
+ return
+ end
+ local cache = caches[name]
+ local layer = layers[name]
+ if not textcolor then
+ textcolor = c_text_d
+ end
+ if not rulecolor then
+ rulecolor = c_origin_d
+ end
+ return function(str)
+ if not str then
+ str = ""
+ end
+ local info = cache[str]
+ if not info then
+ info = make(str,textcolor,rulecolor,layer)
+ cache[str] = info
+ end
+ return copy_node(info)
+ end
+ end
+
+end
diff --git a/tex/context/base/mkiv/trac-vis.mkiv b/tex/context/base/mkiv/trac-vis.mkiv
index a6a3fa5a2..570e6a7c7 100644
--- a/tex/context/base/mkiv/trac-vis.mkiv
+++ b/tex/context/base/mkiv/trac-vis.mkiv
@@ -76,7 +76,7 @@
\to \everyshipout
\appendtoks
- \global\let\syst_visualizers_speedup\relax
+ \glet\syst_visualizers_speedup\relax
\to \t_syst_visualizers_optimize
\def\syst_visualizers_speedup{\the\t_syst_visualizers_optimize}
@@ -122,6 +122,11 @@
\unexpanded\def\showfontitalics
{\clf_setvisual{italic}}
+\unexpanded\def\showglyphdata
+ {\showglyphs
+ \showfontkerns
+ \showfontitalics}
+
\unexpanded\def\showfontexpansion
{\clf_setvisual{expansion}}
diff --git a/tex/context/base/mkiv/type-ini.mkvi b/tex/context/base/mkiv/type-ini.mkvi
index 2ac3ee207..ac5f6af2f 100644
--- a/tex/context/base/mkiv/type-ini.mkvi
+++ b/tex/context/base/mkiv/type-ini.mkvi
@@ -45,18 +45,30 @@
\let\currenttypescripts\empty
\let\currenttypefile \empty
+\installmacrostack\currenttypefile
+
\let\typescriptone \empty % public, used in typescripts
\let\typescripttwo \empty % public, used in typescripts
\let\typescriptthree\empty % public, used in typescripts
+\installmacrostack\typescriptone
+\installmacrostack\typescripttwo
+\installmacrostack\typescriptthree
+
\let\fontclassstyle \empty
+\installmacrostack\fontclassstyle
+
\let\m_font_typescripts_one \empty
\let\m_font_typescripts_two \empty
\let\m_font_typescripts_three\empty
\let\m_font_typescripts_check\empty
\let\m_font_typescripts_match\empty
+\installmacrostack\m_font_typescripts_one
+\installmacrostack\m_font_typescripts_two
+\installmacrostack\m_font_typescripts_three
+
\let\t_font_typescripts\relax % uses as synonym
\installcorenamespace{typescriptcache}
@@ -75,6 +87,9 @@
\let\typescriptmethod\plusone % 1: empty==all==true 2: empty==false
\let\typescriptstate \plustwo % 1: process 2: store
+\installmacrostack\typescriptmethod
+\installmacrostack\typescriptstate
+
\unexpanded\def\starttypescriptcollection
{\dosingleempty\font_typescripts_collection_start}
@@ -95,19 +110,21 @@
\def\font_typescripts_use_one{\let\typescriptmethod\plusone\font_typescripts_use}
\def\font_typescripts_use_two{\let\typescriptmethod\plustwo\font_typescripts_use}
+\installmacrostack\stoptypescript
+
\unexpanded\def\font_typescripts_use[#one][#two][#three]%
- {\pushmacro\m_font_typescripts_one
- \pushmacro\m_font_typescripts_two
- \pushmacro\m_font_typescripts_three
+ {\push_macro_m_font_typescripts_one
+ \push_macro_m_font_typescripts_two
+ \push_macro_m_font_typescripts_three
\edef\m_font_typescripts_one {\truetypescript{#one}}%
\edef\m_font_typescripts_two {\truetypescript{#two}}%
\edef\m_font_typescripts_three{\truetypescript{#three}}%
- \pushmacro\typescriptone
- \pushmacro\typescripttwo
- \pushmacro\typescriptthree
- \pushmacro\typescriptmethod
- \pushmacro\typescriptstate
- \pushmacro\stoptypescript
+ \push_macro_typescriptone
+ \push_macro_typescripttwo
+ \push_macro_typescriptthree
+ \push_macro_typescriptmethod
+ \push_macro_typescriptstate
+ \push_macro_stoptypescript
\typescriptfoundfalse
\let\typescriptstate\plusone % why
\iftracetypescripts
@@ -119,15 +136,15 @@
\font_typescripts_use_display
\fi
\setfalse\c_font_typescripts_first_pass
- \popmacro\stoptypescript
- \popmacro\typescriptstate
- \popmacro\typescriptmethod
- \popmacro\typescriptthree
- \popmacro\typescripttwo
- \popmacro\typescriptone
- \popmacro\m_font_typescripts_three
- \popmacro\m_font_typescripts_two
- \popmacro\m_font_typescripts_one}
+ \pop_macro_stoptypescript
+ \pop_macro_typescriptstate
+ \pop_macro_typescriptmethod
+ \pop_macro_typescriptthree
+ \pop_macro_typescripttwo
+ \pop_macro_typescriptone
+ \pop_macro_m_font_typescripts_three
+ \pop_macro_m_font_typescripts_two
+ \pop_macro_m_font_typescripts_one}
\def\font_typescripts_use_display
{\processcommacommand[\typescriptfiles]\font_typescripts_load_file
@@ -170,10 +187,10 @@
% 1 then, it doesn't get stored without doing that explicitly
\unexpanded\def\loadtypescriptfile[#1]%
- {\pushmacro\typescriptstate
+ {\push_macro_typescriptstate
\let\typescriptstate\plustwo % assumes 2 at the outer level
\clf_loadtypescriptfile{#1}%
- \popmacro\typescriptstate}
+ \pop_macro_typescriptstate}
\unexpanded\def\loadfoundtypescriptfile#1%
{\startreadingfile
@@ -191,30 +208,26 @@
{\global\advance\c_font_typescripts_n_of_preloaded\plusone
\expandafter\normalgdef\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname
{\starttypescript#definitions\stoptypescript}%
- %\normalexpanded{\global\t_font_typescripts{\the\expandafter\t_font_typescripts\noexpand\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}}
- \global\t_font_typescripts\expandafter\expandafter\expandafter
- {\expandafter\the\expandafter\t_font_typescripts
- \csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}
+ \gtoksapp\t_font_typescripts\expandafter
+ {\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}
\def\font_typescripts_collection_start_store#definitions\stoptypescriptcollection
{\global\advance\c_font_typescripts_n_of_preloaded\plusone
\expandafter\normalgdef\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname
{\starttypescriptcollection#definitions\stoptypescriptcollection}%
- %\normalexpanded{\global\t_font_typescripts{\the\expandafter\t_font_typescripts\noexpand\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}}
- \global\t_font_typescripts\expandafter\expandafter\expandafter
- {\expandafter\the\expandafter\t_font_typescripts
- \csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}
+ \gtoksapp\t_font_typescripts\expandafter
+ {\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}
\def\font_typescripts_load_file#filename%
{\setfalse\c_font_typescripts_quit
- \pushmacro\currenttypefile
+ \push_macro_currenttypefile
\def\currenttypefile{#filename}%
\ifconditional\c_font_typescripts_preload
\font_typescript_process_typescript_file_and_store
\else
\font_typescript_process_typescript_file
\fi
- \popmacro\currenttypefile
+ \pop_macro_currenttypefile
\ifconditional\c_font_typescripts_quit
\quitcommalist
\setfalse\c_font_typescripts_quit
@@ -294,8 +307,7 @@
\def\font_typescripts_start_gobble#definitions\stoptypescript{}
\def\font_typescripts_start_document#definitions\stoptypescript
- %{\appendtoks\starttypescript#definitions\stoptypescript\to\c_font_typescripts_document}
- {\c_font_typescripts_document\expandafter{\the\c_font_typescripts_document\starttypescript#definitions\stoptypescript}}
+ {\toksapp\c_font_typescripts_document{\starttypescript#definitions\stoptypescript}}
\def\font_typescripts_start_process % could be a faster \doifelsenextoptionalif needed
{\let\typescriptone \m_font_typescripts_one
@@ -344,10 +356,10 @@
\let\font_typescripts_start_process_again_three\font_typescripts_start_process_yes
\def\font_typescripts_start_process_indeed
- {\pushmacro\fontclass}
+ {\push_macro_fontclass}
\unexpanded\def\stoptypescript
- {\popmacro\fontclass}
+ {\pop_macro_fontclass}
\def\font_typescripts_check#asked#target#followup[#value]% script use value next
{\donefalse
@@ -521,8 +533,8 @@
\let\@@tsdirection \empty
\let\@@tsdesignsize\empty
\geteparameters[\??ts][#settings]% todo raw
- \pushmacro\fontclass
- \pushmacro\fontclassstyle
+ \push_macro_fontclass
+ \push_macro_fontclassstyle
\setcurrentfontclass{#name}%
\savefontclassparameters{#style}\@@tsrscale\@@tsfeatures\@@tsfallbacks\@@tsgoodies\@@tsdesignsize\@@tsdirection
\the\everybeforedefinetypeface}
@@ -536,8 +548,8 @@
\def\font_typefaces_defining_stop
{\the\everyafterdefinetypeface
- \popmacro\fontclassstyle
- \popmacro\fontclass}
+ \pop_macro_fontclassstyle
+ \pop_macro_fontclass}
\def\dofastdefinetypeface#name#style#fontshape#fontsize#settings% called from the lua end (via case d)
{\font_typefaces_define_indeed[#name][#style]%
@@ -597,7 +609,7 @@
{\doifelsenothing{#styles}
{\font_typescripts_inherit_indeed[#name][\s!rm,\s!ss,\s!tt,\s!mm][\fontclass]}
{\doifnot{#name}{#parentclass}
- {\global\let\font_typescripts_inherit_check\font_typescripts_inherit_check_indeed
+ {\glet\font_typescripts_inherit_check\font_typescripts_inherit_check_indeed
\def\font_typescripts_inherit_check_step#style{\setevalue{\??typescriptinheritances#name:#style}{#parentclass}}%
\processcommalist[#styles]\font_typescripts_inherit_check_step}}}
diff --git a/tex/context/base/mkiv/type-set.mkiv b/tex/context/base/mkiv/type-set.mkiv
index 1763de687..c6b0c8841 100644
--- a/tex/context/base/mkiv/type-set.mkiv
+++ b/tex/context/base/mkiv/type-set.mkiv
@@ -132,4 +132,6 @@
\definefilesynonym [type-imp-stixtwo.mkiv] [type-imp-stix.mkiv]
+\definefilesynonym [type-imp-ibmplex.mkiv] [type-imp-plex.mkiv]
+
\protect \endinput
diff --git a/tex/context/base/mkiv/typo-bld.lua b/tex/context/base/mkiv/typo-bld.lua
index 753748a2e..55d74281f 100644
--- a/tex/context/base/mkiv/typo-bld.lua
+++ b/tex/context/base/mkiv/typo-bld.lua
@@ -54,10 +54,12 @@ storage.register("builders/paragraphs/constructors/names", names, "builders.
storage.register("builders/paragraphs/constructors/numbers", numbers, "builders.paragraphs.constructors.numbers")
local trace_page_builder = false trackers.register("builders.page", function(v) trace_page_builder = v end)
+local trace_vbox_builder = false trackers.register("builders.vbox", function(v) trace_vbox_builder = v end)
local trace_post_builder = false trackers.register("builders.post", function(v) trace_post_builder = v end)
-local report_par_builder = logs.reporter("builders","par")
local report_page_builder = logs.reporter("builders","page")
+local report_vbox_builder = logs.reporter("builders","vbox")
+local report_par_builder = logs.reporter("builders","par")
local mainconstructor = nil -- not stored in format
local nofconstructors = 0
@@ -137,7 +139,7 @@ end
-- also for testing (now also surrounding spacing done)
-function builders.paragraphs.constructors.methods.oneline(head,followed_by_display)
+function parbuilders.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)
@@ -193,15 +195,11 @@ function builders.vpack_filter(head,groupcode,size,packtype,maxdepth,direction)
local done = false
if head then
starttiming(builders)
- if trace_vpacking then
+ if trace_vbox_builder then
local before = count_nodes(head)
head, done = vboxactions(head,groupcode,size,packtype,maxdepth,direction)
local after = count_nodes(head)
- if done then
- nodes.processors.tracer("vpack","changed",head,groupcode,before,after,true)
- else
- nodes.processors.tracer("vpack","unchanged",head,groupcode,before,after,true)
- end
+ nodes.processors.tracer("vpack",head,groupcode,before,after,done)
else
head, done = vboxactions(head,groupcode)
end
@@ -254,13 +252,13 @@ function builders.buildpage_filter(groupcode)
if trace_page_builder then
report(groupcode)
end
- return nil, false -- no return value needed
+-- return nil, false -- no return value needed
+ return nil
end
end
-registercallback('vpack_filter', builders.vpack_filter, "vertical spacing etc")
-registercallback('buildpage_filter', builders.buildpage_filter, "vertical spacing etc (mvl)")
-----------------('contribute_filter', builders.contribute_filter, "adding content to lists")
+registercallback('vpack_filter', builders.vpack_filter, "vertical spacing etc")
+registercallback('buildpage_filter', builders.buildpage_filter, "vertical spacing etc (mvl)")
statistics.register("v-node processing time", function()
return statistics.elapsedseconds(builders)
@@ -277,11 +275,21 @@ implement { name = "disableparbuilder", actions = constructors.disable }
-- Here are some tracers:
-local new_kern = nodes.pool.kern
-local new_rule = nodes.pool.rule
-local hpack = nodes.hpack
+local nuts = nodes.nuts
+local tonut = nodes.tonut
local setcolor = nodes.tracers.colors.set
local listtoutf = nodes.listtoutf
+local new_kern = nuts.pool.kern
+local new_rule = nuts.pool.rule
+local hpack = nuts.hpack
+local getheight = nuts.getheight
+local getdepth = nuts.getdepth
+local getdirection = nuts.getdirection
+local getlist = nuts.getlist
+local setwidth = nuts.setwidth
+local setdirection = nuts.setdirection
+local setlink = nuts.setlink
+local tonode = nuts.tonode
local report_hpack = logs.reporter("hpack routine")
local report_vpack = logs.reporter("vpack routine")
@@ -305,8 +313,9 @@ end)
local report, show = false, false
local function hpack_quality(how,detail,n,first,last)
+ n = tonut(n)
if report then
- local str = listtoutf(n.head,"",true,nil,true)
+ local str = listtoutf(getlist(n),"",true,nil,true)
if last <= 0 then
report_hpack("%s hbox: %s",how,str)
elseif first > 0 and first < last then
@@ -316,10 +325,10 @@ local function hpack_quality(how,detail,n,first,last)
end
end
if show then
- local width = 2*65536
- local height = n.height
- local depth = n.depth
- local dir = n.dir
+ local width = 2*65536
+ local height = getheight(n)
+ local depth = getdepth(n)
+ local direction = getdirection(n)
if height < 4*65526 then
height = 4*65526
end
@@ -327,12 +336,11 @@ local function hpack_quality(how,detail,n,first,last)
depth = 2*65526
end
local rule = new_rule(width,height,depth)
- rule.dir = dir
+ setdirection(rule,direction)
if how == "overfull" then
setcolor(rule,"red")
local kern = new_kern(-detail)
- kern.next = rule
- rule.prev = kern
+ setlink(kern,rule)
rule = kern
elseif how == "underfull" then
setcolor(rule,"blue")
@@ -342,9 +350,9 @@ local function hpack_quality(how,detail,n,first,last)
setcolor(rule,"cyan")
end
rule = hpack(rule)
- rule.width = 0
- rule.dir = dir
- return rule
+ setwidth(rule,0)
+ setdirection(rule,direction)
+ return tonode(rule) -- can be a nut
end
end
@@ -387,3 +395,4 @@ end)
-- end,
-- "experimental prevdepth checking"
-- )
+
diff --git a/tex/context/base/mkiv/typo-brk.lua b/tex/context/base/mkiv/typo-brk.lua
index 51760bbf4..76e50ce18 100644
--- a/tex/context/base/mkiv/typo-brk.lua
+++ b/tex/context/base/mkiv/typo-brk.lua
@@ -23,7 +23,6 @@ local settings_to_array = utilities.parsers.settings_to_array
local nuts = nodes.nuts
local tonut = nuts.tonut
-local tonode = nuts.tonode
local getnext = nuts.getnext
local getprev = nuts.getprev
@@ -76,14 +75,14 @@ local new_wordboundary = nodepool.wordboundary
local nodecodes = nodes.nodecodes
local kerncodes = nodes.kerncodes
-local glyph_code = nodecodes.glyph
local kern_code = nodecodes.kern
local math_code = nodecodes.math
local fontkern_code = kerncodes.fontkern
------ userkern_code = kerncodes.userkern
local italickern_code = kerncodes.italiccorrection
+local is_letter = characters.is_letter
+
local typesetters = typesetters
typesetters.breakpoints = typesetters.breakpoints or {}
@@ -241,10 +240,9 @@ end
function breakpoints.handler(head)
local done = false
- local nead = tonut(head)
local attr = nil
local map = nil
- local current = nead
+ local current = head
while current do
local char, id = isglyph(current)
if char then
@@ -313,7 +311,7 @@ function breakpoints.handler(head)
end
end
if not done then
- return head, false
+ return head
end
-- we have hits
local numbers = languages.numbers
@@ -323,17 +321,21 @@ function breakpoints.handler(head)
local stop = data[2]
local cmap = data[3]
local smap = data[4]
--- local lang = getlang(start)
-- -- we do a sanity check for language
+-- local lang = getlang(start)
-- local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""])
-- if smap then
local nleft = smap.nleft
local cleft = 0
local prev = getprev(start)
- local kern = nil
+ local kern = nil
while prev and nleft ~= cleft do
- local id = getid(prev)
- if id == glyph_code then
+ local char, id = isglyph(prev)
+ if char then
+ if not is_letter[char] then
+ cleft = -1
+ break
+ end
cleft = cleft + 1
prev = getprev(prev)
elseif id == kern_code then
@@ -359,6 +361,10 @@ function breakpoints.handler(head)
while next and nright ~= cright do
local char, id = isglyph(next)
if char then
+ if not is_letter[char] then
+ cright = -1
+ break
+ end
if cright == 1 and cmap[char] then
-- let's not make it too messy
break
@@ -383,13 +389,13 @@ function breakpoints.handler(head)
if nright == cright then
local method = methods[smap.type]
if method then
- nead, start = method(nead,start,stop,smap,kern)
+ head, start = method(head,start,stop,smap,kern)
end
end
-- end
end
end
- return tonode(nead), true
+ return head
end
local enabled = false
diff --git a/tex/context/base/mkiv/typo-cap.lua b/tex/context/base/mkiv/typo-cap.lua
index 4dffd1c49..7e8003c62 100644
--- a/tex/context/base/mkiv/typo-cap.lua
+++ b/tex/context/base/mkiv/typo-cap.lua
@@ -18,8 +18,6 @@ local report_casing = logs.reporter("typesetting","casing")
local nodes, node = nodes, node
local nuts = nodes.nuts
-local tonode = nuts.tonode
-local tonut = nuts.tonut
local getnext = nuts.getnext
local getprev = nuts.getprev
@@ -29,6 +27,7 @@ local takeattr = nuts.takeattr
local getfont = nuts.getfont
local getsubtype = nuts.getsubtype
local getchar = nuts.getchar
+local isglyph = nuts.isglyph
local getdisc = nuts.getdisc
local setattr = nuts.setattr
@@ -37,12 +36,12 @@ local setfont = nuts.setfont
local copy_node = nuts.copy
local end_of_math = nuts.end_of_math
-local traverse_id = nuts.traverse_id
local insert_after = nuts.insert_after
local find_attribute = nuts.find_attribute
+local nextglyph = nuts.traversers.glyph
+
local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
local kerncodes = nodes.kerncodes
local glyph_code = nodecodes.glyph
@@ -98,19 +97,6 @@ local function get(a)
extract(a, 0, 8) -- run
end
--- local function get(a)
--- return
--- (a >> 8) & ~(-1 << 8), -- & 0x0FF -- tag
--- (a >> 16) & ~(-1 << 12), -- & 0xFFF -- font
--- (a >> 0) & ~(-1 << 8) -- & 0x0FF -- run
--- end
-
--- print(get(set( 1, 0)))
--- print(get(set( 1, 99)))
--- print(get(set( 2, 96)))
--- print(get(set( 30, 922)))
--- print(get(set(250,4000)))
-
-- a previous implementation used char(0) as placeholder for the larger font, so we needed
-- to remove it before it can do further harm ... that was too tricky as we use char 0 for
-- other cases too
@@ -128,10 +114,9 @@ local categories = characters.categories
-- true false true == mixed
local function replacer(start,codes)
- local char = getchar(start)
- local dc = codes[char]
+ local char, fnt = isglyph(start)
+ local dc = codes[char]
if dc then
- local fnt = getfont(start)
local ifc = fontchar[fnt]
if type(dc) == "table" then
for i=1,#dc do
@@ -149,13 +134,11 @@ local function replacer(start,codes)
insert_after(start,start,g)
end
end
- return start, true
elseif ifc[dc] then
setchar(start,dc)
- return start, true
end
end
- return start, false
+ return start
end
local registered, n = { }, 0
@@ -191,9 +174,9 @@ local function Words(start,attr,lastfont,n,count,where,first) -- looks quite com
end
if count == 1 and where ~= "post" then
replacer(first or start,uccodes)
- return start, true, true
+ return start, true
else
- return start, false, true
+ return start, true
end
end
@@ -203,9 +186,9 @@ local function Word(start,attr,lastfont,n,count,where,first)
end
local function camel(start,attr,lastfont,n,count,where,first)
- local _, done_1 = word(start,attr,lastfont,n,count,where,first)
- local _, done_2 = Words(start,attr,lastfont,n,count,where,first)
- return start, done_1 or done_2, true
+ word(start,attr,lastfont,n,count,where,first)
+ Words(start,attr,lastfont,n,count,where,first)
+ return start, true
end
-- local function mixed(start,attr,lastfont,n,count,where,first)
@@ -216,19 +199,16 @@ end
-- local char = getchar(first)
-- local dc = uccodes[char]
-- if not dc then
--- return start, false, true
+-- -- quit
-- elseif dc == char then
-- local lfa = lastfont[n]
-- if lfa then
-- setfont(first,lfa)
--- return start, true, true
--- else
--- return start, false, true
-- end
-- else
-- replacer(first or start,uccodes)
--- return start, true, true
-- end
+-- return start, true
-- end
local function mixed(start,attr,lastfont,n,count,where,first)
@@ -239,38 +219,33 @@ local function mixed(start,attr,lastfont,n,count,where,first)
local char = getchar(used)
local dc = uccodes[char]
if not dc then
- return start, false, true
+ -- quit
elseif dc == char then
local lfa = lastfont[n]
if lfa then
setfont(used,lfa)
- return start, true, true
- else
- return start, false, true
end
- else
- if check_kerns then
- local p = getprev(used)
- if p and getid(p) == glyph_code then
- local c = lccodes[char]
- local c = type(c) == "table" and c[1] or c
- replacer(used,uccodes)
- local fp = getfont(p)
- local fc = getfont(used)
- if fp ~= fc then
- local k = fonts.getkern(fontdata[fp],getchar(p),c)
- if k ~= 0 then
- insert_after(p,p,newkern(k))
- end
+ elseif check_kerns then
+ local p = getprev(used)
+ if p and getid(p) == glyph_code then
+ local c = lccodes[char]
+ local c = type(c) == "table" and c[1] or c
+ replacer(used,uccodes)
+ local fp = getfont(p)
+ local fc = getfont(used)
+ if fp ~= fc then
+ local k = fonts.getkern(fontdata[fp],getchar(p),c)
+ if k ~= 0 then
+ insert_after(p,p,newkern(k))
end
- else
- replacer(used,uccodes)
end
else
replacer(used,uccodes)
end
- return start, true, true
+ else
+ replacer(used,uccodes)
end
+ return start, true
end
local function Capital(start,attr,lastfont,n,count,where,first,once) -- 3
@@ -284,11 +259,11 @@ local function Capital(start,attr,lastfont,n,count,where,first,once) -- 3
end
end
end
- local s, d, c = replacer(first or start,uccodes)
+ local s, c = replacer(first or start,uccodes)
if once then
lastfont[n] = false -- here
end
- return start, d, c
+ return start, c
end
local function capital(start,attr,lastfont,n,where,count,first,count) -- 4
@@ -296,7 +271,7 @@ local function capital(start,attr,lastfont,n,where,count,first,count) -- 4
end
local function none(start,attr,lastfont,n,count,where,first)
- return start, false, true
+ return start, true
end
local function randomized(start,attr,lastfont,n,count,where,first)
@@ -311,7 +286,7 @@ local function randomized(start,attr,lastfont,n,count,where,first)
local n = getrandom("capital lu",0x41,0x5A)
if tfm[n] then -- this also intercepts tables
setchar(used,n)
- return start, true
+ return start
end
end
elseif kind == "ll" then
@@ -319,11 +294,11 @@ local function randomized(start,attr,lastfont,n,count,where,first)
local n = getrandom("capital ll",0x61,0x7A)
if tfm[n] then -- this also intercepts tables
setchar(used,n)
- return start, true
+ return start
end
end
end
- return start, false
+ return start
end
register(variables.WORD, WORD) -- 1
@@ -341,10 +316,9 @@ register(variables.cap, variables.capital) -- clone
register(variables.Cap, variables.Capital) -- clone
function cases.handler(head) -- not real fast but also not used on much data
- local start = tonut(head)
+ local start = head
local lastfont = { }
local lastattr = nil
- local done = false
local count = 0
local previd = nil
local prev = nil
@@ -367,10 +341,7 @@ function cases.handler(head) -- not real fast but also not used on much data
end
local action = actions[n] -- map back to low number
if action then
- start, ok = action(start,attr,lastfont,n,count)
- if ok then
- done = true
- end
+ start = action(start,attr,lastfont,n,count)
if trace_casing then
report_casing("case trigger %a, instance %a, fontid %a, result %a",n,m,id,ok)
end
@@ -396,32 +367,38 @@ function cases.handler(head) -- not real fast but also not used on much data
local pre, post, replace = getdisc(start)
if replace then
local cnt = count
- for g in traverse_id(glyph_code,replace) do
+ for g in nextglyph, replace do
cnt = cnt + 1
takeattr(g,a_cases)
-- setattr(g,a_cases,unsetvalue)
- local _, _, quit = action(start,attr,lastfont,n,cnt,"replace",g)
- if quit then break end
+ local h, quit = action(start,attr,lastfont,n,cnt,"replace",g)
+ if quit then
+ break
+ end
end
end
if pre then
local cnt = count
- for g in traverse_id(glyph_code,pre) do
+ for g in nextglyph, pre do
cnt = cnt + 1
takeattr(g,a_cases)
-- setattr(g,a_cases,unsetvalue)
- local _, _, quit = action(start,attr,lastfont,n,cnt,"pre",g)
- if quit then break end
+ local h, quit = action(start,attr,lastfont,n,cnt,"pre",g)
+ if quit then
+ break
+ end
end
end
if post then
local cnt = count
- for g in traverse_id(glyph_code,post) do
+ for g in nextglyph, post do
cnt = cnt + 1
takeattr(g,a_cases)
-- setattr(g,a_cases,unsetvalue)
- local _, _, quit = action(start,attr,lastfont,n,cnt,"post",g)
- if quit then break end
+ local h, quit = action(start,attr,lastfont,n,cnt,"post",g)
+ if quit then
+ break
+ end
end
end
end
@@ -441,17 +418,16 @@ function cases.handler(head) -- not real fast but also not used on much data
start = getnext(start)
end
end
- return head, done
+ return head
end
-- function cases.handler(head) -- not real fast but also not used on much data
--- local attr, start = find_attribute(tonut(head),a_cases)
+-- local attr, start = find_attribute(head,a_cases)
-- if not start then
-- return head, false
-- end
-- local lastfont = { }
-- local lastattr = nil
--- local done = false
-- local count = 0
-- local previd = nil
-- local prev = nil
@@ -475,10 +451,7 @@ end
-- end
-- local action = actions[n] -- map back to low number
-- if action then
--- start, ok = action(start,attr,lastfont,n,count)
--- if ok then
--- done = true
--- end
+-- start = action(start,attr,lastfont,n,count)
-- if trace_casing then
-- report_casing("case trigger %a, instance %a, fontid %a, result %a",n,m,id,ok)
-- end
@@ -504,32 +477,38 @@ end
-- local pre, post, replace = getdisc(start)
-- if replace then
-- local cnt = count
--- for g in traverse_id(glyph_code,replace) do
+-- for g in glyph_code, replace do
-- cnt = cnt + 1
-- takeattr(g,a_cases)
-- -- setattr(g,a_cases,unsetvalue)
--- local _, _, quit = action(start,attr,lastfont,n,cnt,"replace",g)
--- if quit then break end
+-- local h, quit = action(start,attr,lastfont,n,cnt,"replace",g)
+-- if quit then
+-- break
+-- end
-- end
-- end
-- if pre then
-- local cnt = count
--- for g in traverse_id(glyph_code,pre) do
+-- for g in nextglyph, pre do
-- cnt = cnt + 1
-- takeattr(g,a_cases)
-- -- setattr(g,a_cases,unsetvalue)
--- local _, _, quit = action(start,attr,lastfont,n,cnt,"pre",g)
--- if quit then break end
+-- local h, quit = action(start,attr,lastfont,n,cnt,"pre",g)
+-- if quit then
+-- break
+-- end
-- end
-- end
-- if post then
-- local cnt = count
--- for g in traverse_id(glyph_code,post) do
+-- for g in nextglyph, post do
-- cnt = cnt + 1
-- takeattr(g,a_cases)
-- -- setattr(g,a_cases,unsetvalue)
--- local _, _, quit = action(start,attr,lastfont,n,cnt,"post",g)
--- if quit then break end
+-- local h, quit = action(start,attr,lastfont,n,cnt,"post",g)
+-- if quit then
+-- break
+-- end
-- end
-- end
-- end
@@ -555,26 +534,22 @@ end
-- attr, start = find_attribute(start,a_cases)
-- end
-- end
--- return head, done
+-- return head
-- end
-- function cases.handler(head) -- let's assume head doesn't change ... no reason
--- local done = false
-- local lastfont = { }
--- for first, last, size, attr in nuts.words(tonut(head),a_cases) do
+-- for first, last, size, attr in nuts.words(head,a_cases) do
-- local n, id, m = get(attr)
-- if lastfont[n] == nil then
-- lastfont[n] = id
-- end
-- local action = actions[n]
-- if action then
--- local _, ok = action(first,attr,lastfont,n)
--- if ok then
--- done = true
--- end
+-- action(first,attr,lastfont,n)
-- end
-- end
--- return head, done
+-- return head
-- end
local enabled = false
diff --git a/tex/context/base/mkiv/typo-cap.mkiv b/tex/context/base/mkiv/typo-cap.mkiv
index 4d1272e10..890b08186 100644
--- a/tex/context/base/mkiv/typo-cap.mkiv
+++ b/tex/context/base/mkiv/typo-cap.mkiv
@@ -81,20 +81,23 @@
% todo: names casings
-\unexpanded\def\WORD {\groupedcommand{\setcharactercasing[\v!WORD ]}{}}
-\unexpanded\def\word {\groupedcommand{\setcharactercasing[\v!word ]}{}}
-\unexpanded\def\Word {\groupedcommand{\setcharactercasing[\v!Word ]}{}}
-\unexpanded\def\Words{\groupedcommand{\setcharactercasing[\v!Words]}{}}
-\unexpanded\def\camel{\groupedcommand{\setcharactercasing[\v!camel]}{}}
-
-% This might become:
-%
-% \unexpanded\def\WORD {\bgroup\def\g_word{\setcharactercasing[\v!WORD ]}\afterassignment\g_word\let\nexttoken}
-% \unexpanded\def\word {\bgroup\def\g_word{\setcharactercasing[\v!word ]}\afterassignment\g_word\let\nexttoken}
-% \unexpanded\def\Word {\bgroup\def\g_word{\setcharactercasing[\v!Word ]}\afterassignment\g_word\let\nexttoken}
-% \unexpanded\def\Words{\bgroup\def\g_word{\setcharactercasing[\v!Words]}\afterassignment\g_word\let\nexttoken}
-%
-% so no longer {\Word test} and { } mandate (also later \groupedcommands will go)
+% \unexpanded\def\WORD {\groupedcommand{\setcharactercasing[\v!WORD ]}{}}
+% \unexpanded\def\word {\groupedcommand{\setcharactercasing[\v!word ]}{}}
+% \unexpanded\def\Word {\groupedcommand{\setcharactercasing[\v!Word ]}{}}
+% \unexpanded\def\Words{\groupedcommand{\setcharactercasing[\v!Words]}{}}
+% \unexpanded\def\camel{\groupedcommand{\setcharactercasing[\v!camel]}{}}
+
+\unexpanded\def\typo_capitale_WORD {\clf_setcharactercasing{\v!WORD }\fontid\font}
+\unexpanded\def\typo_capitale_word {\clf_setcharactercasing{\v!word }\fontid\font}
+\unexpanded\def\typo_capitale_Word {\clf_setcharactercasing{\v!Word }\fontid\font}
+\unexpanded\def\typo_capitale_Words{\clf_setcharactercasing{\v!Words}\fontid\font}
+\unexpanded\def\typo_capitale_camel{\clf_setcharactercasing{\v!camel}\fontid\font}
+
+\unexpanded\def\WORD {\triggergroupedcommandcs\typo_capitale_WORD }
+\unexpanded\def\word {\triggergroupedcommandcs\typo_capitale_word }
+\unexpanded\def\Word {\triggergroupedcommandcs\typo_capitale_Word }
+\unexpanded\def\Words{\triggergroupedcommandcs\typo_capitale_Words}
+\unexpanded\def\camel{\triggergroupedcommandcs\typo_capitale_camel}
\let\WORDS\WORD
\let\words\word
@@ -176,16 +179,27 @@
\sc
\clf_setcharactercasing{\currentcapitals}\fontid\font}
-\unexpanded\def\pseudosmallcapped{\groupedcommand{\typo_capitals_set_fake\v!WORD }\donothing} % all upper
-\unexpanded\def\pseudoSmallcapped{\groupedcommand{\typo_capitals_set_fake\v!capital}\donothing} % one upper + font
-\unexpanded\def\pseudoSmallCapped{\groupedcommand{\typo_capitals_set_fake\v!Capital}\donothing} % some upper + font
-\unexpanded\def\pseudoMixedCapped{\groupedcommand{\typo_capitals_set_fake\v!mixed }\donothing} % UpperCase
+% \unexpanded\def\pseudosmallcapped{\groupedcommand{\typo_capitals_set_fake\v!WORD }\donothing} % all upper
+% \unexpanded\def\pseudoSmallcapped{\groupedcommand{\typo_capitals_set_fake\v!capital}\donothing} % one upper + font
+% \unexpanded\def\pseudoSmallCapped{\groupedcommand{\typo_capitals_set_fake\v!Capital}\donothing} % some upper + font
+% \unexpanded\def\pseudoMixedCapped{\groupedcommand{\typo_capitals_set_fake\v!mixed }\donothing} % UpperCase
+%
+% \unexpanded\def\realsmallcapped {\groupedcommand{\typo_capitals_set_real\v!WORD }\donothing} % all lower
+% \unexpanded\def\realSmallcapped {\groupedcommand{\typo_capitals_set_real\v!Word }\donothing} % one upper + font
+% \unexpanded\def\realSmallCapped {\groupedcommand{\typo_capitals_set_real\v!Words }\donothing} % some upper
+%
+% \unexpanded\def\notsmallcapped {\groupedcommand{\typo_capitals_set_fake\v!word }\donothing}
+
+\unexpanded\def\pseudosmallcapped{\triggergroupedcommandcs\font_style_pseudosmallcapped}
+\unexpanded\def\pseudoSmallcapped{\triggergroupedcommandcs\font_style_pseudoSmallcapped}
+\unexpanded\def\pseudoSmallCapped{\triggergroupedcommandcs\font_style_pseudoSmallCapped}
+\unexpanded\def\pseudoMixedCapped{\triggergroupedcommandcs\font_style_pseudoMixedCapped}
-\unexpanded\def\realsmallcapped {\groupedcommand{\typo_capitals_set_real\v!WORD }\donothing} % all lower
-\unexpanded\def\realSmallcapped {\groupedcommand{\typo_capitals_set_real\v!Word }\donothing} % one upper + font
-\unexpanded\def\realSmallCapped {\groupedcommand{\typo_capitals_set_real\v!Words }\donothing} % some upper
+\unexpanded\def\realsmallcapped {\triggergroupedcommandcs\font_style_realsmallcapped}
+\unexpanded\def\realSmallcapped {\triggergroupedcommandcs\font_style_realSmallcapped}
+\unexpanded\def\realSmallCapped {\triggergroupedcommandcs\font_style_realSmallCapped}
-\unexpanded\def\notsmallcapped {\groupedcommand{\typo_capitals_set_fake\v!word }\donothing}
+\unexpanded\def\notsmallcapped {\triggergroupedcommandcs\font_style_notsmallcapped}
\unexpanded\def\font_style_pseudosmallcapped{\typo_capitals_set_fake\v!WORD } % all upper
\unexpanded\def\font_style_pseudoSmallcapped{\typo_capitals_set_fake\v!capital} % one upper + font
@@ -285,7 +299,9 @@
%
% \definestartstop[randomized][\c!before=\dosetattribute{case}{8},\c!after=]
-\unexpanded\def\randomizetext{\groupedcommand{\attribute\caseattribute\pluseight}{}}
+% \unexpanded\def\randomizetext{\groupedcommand{\attribute\caseattribute\pluseight}{}}
+
+\unexpanded\def\randomizetext{\triggergroupedcommand{\attribute\caseattribute\pluseight}}
\definestartstop[randomized][\c!before=\dosetattribute{case}{8},\c!after=]
diff --git a/tex/context/base/mkiv/typo-chr.lua b/tex/context/base/mkiv/typo-chr.lua
index 80497a492..15d14c860 100644
--- a/tex/context/base/mkiv/typo-chr.lua
+++ b/tex/context/base/mkiv/typo-chr.lua
@@ -6,40 +6,40 @@ if not modules then modules = { } end modules ['typo-chr'] = {
license = "see context related readme files"
}
--- local nodecodes = nodes.nodecodes
--- local whatsitcodes = nodes.whatsitcodes
--- local glyph_code = nodecodes.glyph
--- local whatsit_code = nodecodes.whatsit
--- local user_code = whatsitcodes.userdefined
+-- This module can be optimized.
+
+-- local nodecodes = nodes.nodecodes
+-- local whatsitcodes = nodes.whatsitcodes
+--
+-- local glyph_code = nodecodes.glyph
+-- local whatsit_code = nodecodes.whatsit
--
--- local stringusernode = nodes.pool.userstring
+-- local userwhatsit_code = whatsitcodes.userdefined
--
--- local nuts = nodes.nuts
--- local pool = nuts.pool
+-- local stringusernode = nodes.pool.userstring
--
--- local tonut = nuts.tonut
--- local tonode = nuts.tonode
--- local getid = nuts.getid
--- local getprev = nuts.getprev
--- local getsubtype = nuts.getsubtype
--- local getchar = nuts.getchar
--- local getfield = nuts.getfield
+-- local nuts = nodes.nuts
+-- local pool = nuts.pool
--
--- local remove_node = nuts.remove
--- local traverse_by_id = nuts.traverse_id
+-- local getid = nuts.getid
+-- local getprev = nuts.getprev
+-- local getchar = nuts.getchar
+-- local getdata = nuts.getdata
+-- local getfield = nuts.getfield
--
--- local signal = pool.userids.signal
+-- local remove_node = nuts.remove
+-- local nextwhatsit = nuts.traversers.whatsit
--
--- local is_punctuation = characters.is_punctuation
+-- local signal = pool.userids.signal
+--
+-- local is_punctuation = characters.is_punctuation
--
-- local actions = {
-- removepunctuation = function(head,n)
-- local prev = getprev(n)
-- if prev then
--- if getid(prev) == glyph_code then
--- if is_punctuation[getchar(prev)] then
--- head = remove_node(head,prev,true)
--- end
+-- if getid(prev) == glyph_code and is_punctuation[getchar(prev)] then
+-- head = remove_node(head,prev,true)
-- end
-- end
-- return head
@@ -51,23 +51,18 @@ if not modules then modules = { } end modules ['typo-chr'] = {
-- typesetters.signals = { }
--
-- function typesetters.signals.handler(head)
--- local h = tonut(head)
-- local done = false
--- for n in traverse_by_id(whatsit_code,h) do
--- if getsubtype(n) == user_code and getfield(n,"user_id") == signal and getfield(n,"type") == 115 then
--- local action = actions[getfield(n,"value")]
+-- for n, subtype in nextwhatsit, head do
+-- if subtype == userwhatsit_code and getfield(n,"user_id") == signal and getfield(n,"type") == 115 then
+-- local action = actions[getdata(n)]
-- if action then
--- h = action(h,n)
+-- head = action(h,n)
-- end
--- h = remove_node(h,n,true)
+-- head = remove_node(head,n,true)
-- done = true
-- end
-- end
--- if done then
--- return tonode(h), true
--- else
--- return head
--- end
+-- return head, done
-- end
--
-- local enabled = false
@@ -88,35 +83,44 @@ if not modules then modules = { } end modules ['typo-chr'] = {
local insert, remove = table.insert, table.remove
-local context = context
+local context = context
+local ctx_doifelse = commands.doifelse
+
+local nodecodes = nodes.nodecodes
+local boundarycodes = nodes.boundarycodes
+local subtypes = nodes.subtypes
+
+local glyph_code = nodecodes.glyph
+local localpar_code = nodecodes.localpar
+local boundary_code = nodecodes.boundary
-local nodecodes = nodes.nodecodes
-local glyph_code = nodecodes.glyph
-local localpar_code = nodecodes.localpar
+local wordboundary_code = boundarycodes.word
-local texnest = tex.nest
-local flush_node = node.flush_node
-local flush_list = node.flush_list
+local texgetnest = tex.getnest -- to be used
+local texsetcount = tex.setcount
-local settexattribute = tex.setattribute
-local punctuation = characters.is_punctuation
+local flush_node = node.flush_node
+local flush_list = node.flush_list
-local variables = interfaces.variables
-local v_all = variables.all
-local v_reset = variables.reset
+local settexattribute = tex.setattribute
+local punctuation = characters.is_punctuation
-local a_marked = attributes.numbers['marked']
-local lastmarked = 0
-local marked = {
+local variables = interfaces.variables
+local v_all = variables.all
+local v_reset = variables.reset
+
+local stack = { }
+
+local a_marked = attributes.numbers['marked']
+local lastmarked = 0
+local marked = {
[v_all] = 1,
[""] = 1,
[v_reset] = attributes.unsetvalue,
}
-local stack = { }
-
local function pickup()
- local list = texnest[texnest.ptr]
+ local list = texgetnest()
if list then
local tail = list.tail
if tail and tail.id == glyph_code and punctuation[tail.char] then
@@ -171,8 +175,7 @@ local function pickup(head,tail,str)
while true do
local prev = first.prev
if prev and prev[a_marked] == attr then
- local id = prev.id
- if id == localpar_code then
+ if prev.id == localpar_code then -- and prev.subtype == 0
break
else
first = prev
@@ -187,7 +190,7 @@ end
local actions = {
remove = function(specification)
- local list = texnest[texnest.ptr]
+ local list = texgetnest()
if list then
local head = list.head
local tail = list.tail
@@ -250,3 +253,95 @@ interfaces.implement {
actions = markcontent,
arguments = "string",
}
+
+-- We just put these here.
+
+interfaces.implement {
+ name = "lastnodeidstring",
+ public = true,
+ actions = function()
+ local list = texgetnest() -- "top"
+ local okay = false
+ if list then
+ local tail = list.tail
+ if tail then
+ okay = nodecodes[tail.id]
+ end
+ end
+ context(okay or "")
+ end,
+}
+
+-- local t_lastnodeid = token.create("c_syst_last_node_id")
+--
+-- interfaces.implement {
+-- name = "lastnodeid",
+-- public = true,
+-- actions = function()
+-- ...
+-- tex.setcount("c_syst_last_node_id",okay)
+-- context.sprint(t_lastnodeid)
+-- end,
+-- }
+
+interfaces.implement {
+ name = "lastnodeid",
+ actions = function()
+ local list = texgetnest() -- "top"
+ local okay = -1
+ if list then
+ local tail = list.tail
+ if tail then
+ okay = tail.id
+ end
+ end
+ texsetcount("c_syst_last_node_id",okay)
+ end,
+}
+
+interfaces.implement {
+ name = "lastnodesubtypestring",
+ public = true,
+ actions = function()
+ local list = texgetnest() -- "top"
+ local okay = false
+ if list then
+ local tail = list.tail
+ if head then
+ okay = subtypes[tail.id][tail.subtype]
+ end
+ end
+ context(okay or "")
+ end,
+}
+
+local function lastnodeequals(id,subtype)
+ local list = texgetnest() -- "top"
+ local okay = false
+ if list then
+ local tail = list.tail
+ if tail then
+ local i = tail.id
+ okay = i == id or i == nodecodes[id]
+ if subtype then
+ local s = tail.subtype
+ okay = s == subtype or s == subtypes[i][subtype]
+ end
+ end
+ end
+ ctx_doifelse(okay)
+end
+
+interfaces.implement {
+ name = "lastnodeequals",
+ arguments = "2 strings",
+ actions = lastnodeequals,
+}
+
+interfaces.implement {
+ name = "atwordboundary",
+ actions = function()
+ lastnodeequals(boundary_code,wordboundary_code)
+ end,
+}
+
diff --git a/tex/context/base/mkiv/typo-chr.mkiv b/tex/context/base/mkiv/typo-chr.mkiv
index c92c4562e..365c79e51 100644
--- a/tex/context/base/mkiv/typo-chr.mkiv
+++ b/tex/context/base/mkiv/typo-chr.mkiv
@@ -79,4 +79,23 @@
\def\typo_marked_remove[#1]%
{\clf_pickupmarkedcontent action{remove}mark{#1}\relax}
+%D A few helpers (put here for convenience):
+%D
+%D \starttyping
+%D test test\doifelselastnode{boundary}{word}{YES}{NOP}test
+%D test test\wordboundary \doifelselastnode{boundary}{word}{YES}{NOP}test
+%D test test\wordboundary \doifelseatwordboundary{YES}{NOP}test
+%D test test \lastnodeidstring test
+%D test test\lastnodeidstring test
+%D test test\number\lastnodeid test
+%D \stoptyping
+
+\newcount\c_syst_last_node_id
+
+\unexpanded\def\doifelselastnode {\clf_lastnodeequals}
+\unexpanded\def\doifelseatwordboundary{\clf_atwordboundary}
+\unexpanded\def\lastnodeid {\clf_lastnodeid\c_syst_last_node_id}
+% \lastnodeidstring % public expandable
+% \lastnodesubstring % public expandable
+
\protect \endinput
diff --git a/tex/context/base/mkiv/typo-cln.lua b/tex/context/base/mkiv/typo-cln.lua
index b7187eaeb..b9b0e7d6c 100644
--- a/tex/context/base/mkiv/typo-cln.lua
+++ b/tex/context/base/mkiv/typo-cln.lua
@@ -31,15 +31,13 @@ local enableaction = nodes.tasks.enableaction
local texsetattribute = tex.setattribute
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local getchar = nuts.getchar
local getattr = nuts.getattr
local setattr = nuts.setattr
local setchar = nuts.setchar
-local traverse_id = nuts.traverse_id
+local nextglyph = nuts.traversers.glyph
local unsetvalue = attributes.unsetvalue
@@ -58,9 +56,8 @@ local resetter = { -- this will become an entry in char-def
-- cleaning comes first.
function cleaners.handler(head)
- local inline, done = false, false
- for n in traverse_id(glyph_code,tonut(head)) do
- local char = getchar(n)
+ local inline = false
+ for n, char, font in nextglyph, head do
if resetter[char] then
inline = false
elseif not inline then
@@ -71,7 +68,6 @@ function cleaners.handler(head)
-- some day, not much change that \SS ends up here
else
setchar(n,upper)
- done = true
if trace_autocase then
report_autocase("")
end
@@ -80,7 +76,7 @@ function cleaners.handler(head)
inline = true
end
end
- return head, done
+ return head
end
-- see typo-cap for a more advanced settings handler .. not needed now
diff --git a/tex/context/base/mkiv/typo-del.mkiv b/tex/context/base/mkiv/typo-del.mkiv
index d12be6bcf..2ce98841e 100644
--- a/tex/context/base/mkiv/typo-del.mkiv
+++ b/tex/context/base/mkiv/typo-del.mkiv
@@ -71,35 +71,48 @@
\setnewconstant\boundarycharactermode\plusone
+% old: skip symbol skip
+% new: bound skip symbol skip bound
+
\unexpanded\def\midboundarycharacter#1#2%
{\ifcase\boundarycharactermode
\or
- %\nobreak
+ \removeunwantedspaces
+ \wordboundary
\hskip\hspaceamount\currentusedlanguage{#2}%
\usedlanguageparameter#1%
- %\nobreak
\hskip\hspaceamount\currentusedlanguage{#2}%
+ \wordboundary
+ \ignorespaces
\or
\usedlanguageparameter#1%
\fi
\boundarycharactermode\plusone}
+% old: symbol nobreak skip
+% new: symbol nobreak skip wordboundary
+
\unexpanded\def\leftboundarycharacter#1#2%
{\ifcase\boundarycharactermode
\or
\usedlanguageparameter#1%
\nobreak
- \hskip\hspaceamount\currentusedlanguage{#2}%
+ \hskip\hspaceamount\currentusedlanguage{#2}% why not a kern
+ \wordboundary
\or
\usedlanguageparameter#1%
\fi
\boundarycharactermode\plusone}
+% old: preword skip symbol
+% new: bound nobreak skip symbol
+
\unexpanded\def\rightboundarycharacter#1#2%
{\ifcase\boundarycharactermode
\or
- \prewordbreak %\nobreak
- \hskip\hspaceamount\currentusedlanguage{#2}%
+ \wordboundary
+ \nobreak
+ \hskip\hspaceamount\currentusedlanguage{#2}% why not a kern
\usedlanguageparameter#1%
\or
\usedlanguageparameter#1%
@@ -212,10 +225,15 @@
%D \typebuffer
%D \getbuffer
-\unexpanded\def\startsubsentence{\beginofsubsentence\prewordbreak\beginofsubsentencespacing\typo_subsentence_cleanup_start}
-\unexpanded\def\stopsubsentence {\typo_subsentence_cleanup_stop\endofsubsentencespacing\prewordbreak\endofsubsentence}
-\unexpanded\def\subsentence {\groupedcommand\startsubsentence\stopsubsentence}
-\unexpanded\def\midsubsentence {\typo_subsentence_cleanup_start\prewordbreak\midsentence\prewordbreak\typo_subsentence_cleanup_stop}
+%unexpanded\def\startsubsentence{\beginofsubsentence\prewordbreak\beginofsubsentencespacing\typo_subsentence_cleanup_start}
+%unexpanded\def\stopsubsentence {\typo_subsentence_cleanup_stop\endofsubsentencespacing\prewordbreak\endofsubsentence}
+%unexpanded\def\subsentence {\groupedcommandcs\startsubsentence\stopsubsentence}
+%unexpanded\def\midsubsentence {\typo_subsentence_cleanup_start\prewordbreak\midsentence\prewordbreak\typo_subsentence_cleanup_stop}
+
+\unexpanded\def\startsubsentence{\beginofsubsentence\wordboundary\beginofsubsentencespacing\wordboundary\typo_subsentence_cleanup_start}
+\unexpanded\def\stopsubsentence {\typo_subsentence_cleanup_stop\wordboundary\endofsubsentencespacing\wordboundary\endofsubsentence}
+\unexpanded\def\subsentence {\groupedcommandcs\startsubsentence\stopsubsentence}
+\unexpanded\def\midsubsentence {\typo_subsentence_cleanup_start\wordboundary\midsentence\wordboundary\typo_subsentence_cleanup_stop}
\definehspace [quotation] [\zeropoint]
\definehspace [interquotation] [.125em]
@@ -277,6 +295,8 @@
\let\currentdelimitedtext\s!unknown
+\installglobalmacrostack\currentdelimitedtext
+
\let\delimitedtextlevel\!!zerocount
\def\c_typo_delimited_nesting{\csname\??delimitedtextlevel\currentparentdelimitedtext\endcsname}
@@ -301,6 +321,8 @@
\let\currentdelimitedlanguage\empty
+\installglobalmacrostack\currentdelimitedlanguage
+
\def\typo_delimited_set_language_nop
{\setusedlanguage{\delimitedtextparameter\c!language}}
@@ -333,8 +355,8 @@
\let\m_delimited_argument\empty}
\def\typo_delimited_push#1#2%
- {\globalpushmacro\currentdelimitedtext % can we combine these two
- \globalpushmacro\currentdelimitedlanguage % the language used for hyphenation
+ {\push_macro_currentdelimitedtext % can we combine these two
+ \push_macro_currentdelimitedlanguage % the language used for hyphenation
\edef\currentdelimitedtext{#1}%
\edef\m_delimited_argument{#2}%
\ifx\m_delimited_argument\empty
@@ -350,8 +372,8 @@
\def\typo_delimited_pop
{\global\advance\c_typo_delimited_nesting\minusone
- \globalpopmacro\currentdelimitedlanguage
- \globalpopmacro\currentdelimitedtext}
+ \pop_macro_currentdelimitedlanguage
+ \pop_macro_currentdelimitedtext}
\installcorenamespace{delimitedtext}
\installcorenamespace{delimitedtextlevel}
@@ -414,6 +436,8 @@
\dostoptagged
\ignorespaces}
+\newconditional\c_typo_delimited_repeating
+
\def\typo_delimited_start_other
{\edef\p_delimited_repeat{\delimitedtextparameter\c!repeat}%
\ifx\p_delimited_repeat\v!yes
@@ -421,6 +445,7 @@
\else
\let\typo_delimited_repeat\relax
\fi
+ \setfalse\c_typo_delimited_repeating
\edef\p_delimited_location{\delimitedtextparameter\c!location}%
\ifx\p_delimited_location\v!paragraph
\singleexpandafter\typo_delimited_start_par
@@ -493,7 +518,7 @@
\let\typo_delimited_stop_par_indeed\stopnarrower
\fi
% so far
- \pushmacro\checkindentation
+ \push_macro_checkindentation
\useindentingparameter\delimitedtextparameter
%
\begingroup
@@ -515,7 +540,7 @@
{\typo_delimited_stop_content
\rightdelimitedtextmark
\carryoverpar\endgroup % new per 2013-01-21 ... please left floats
- \popmacro\checkindentation
+ \pop_macro_checkindentation
\typo_delimited_stop_par_indeed
\delimitedtextparameter\c!after
\edef\p_delimited_spaceafter{\delimitedtextparameter\c!spaceafter}%
@@ -680,30 +705,37 @@
% test test test
% \stoptext
-\def\typo_delimited_handle_middle#1%
- {\typo_delimited_stop_content
- \begingroup
- \usedelimitedtextstyleandcolor\c!symstyle\c!symcolor
- \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
- \ifdim\wd\scratchbox>\zeropoint
- \ifdim\lastkern=\d_typo_delimited_signal
- \unkern
- \hskip\hspaceamount\currentusedlanguage{interquotation}%
+% We have no real test case for this and it's broken already for a while,
+% even in \MKII. Maybe we should to this in \LUA. Only Italian has the
+% middlespeech parameter set.
+
+\def\typo_delimited_handle_middle#1% special case
+ {\ifconditional\c_typo_delimited_repeating
+ \begingroup
+ \usedelimitedtextstyleandcolor\c!symstyle\c!symcolor
+ \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
+ \ifdim\wd\scratchbox>\zeropoint
+ \ifdim\lastkern=\d_typo_delimited_signal
+ \unkern
+ \hskip\hspaceamount\currentusedlanguage{interquotation}%
+ \else % maybe an option:
+ %\edef\p_delimited_margin{\delimitedtextparameter\c!location}%
+ %\ifx\p_delimited_margin\v!margin
+ % \hskip-\wd\scratchbox
+ %\fi
+ \fi
+ \strut % new, needed below
+ \dostarttagged\t!delimitedsymbol\empty
+ \dotagsetdelimitedsymbol\s!middle
+ \delimitedtextparameter#1% unhbox\scratchbox
+ \dostoptagged
+ % \penalty\plustenthousand % else overfull boxes, but that's better than dangling periods
+ \kern\d_typo_delimited_signal % +- \prewordbreak
\fi
- \ifhmode % else funny pagebeaks
- \penalty\plustenthousand
- \hskip\zeropoint % == \prewordbreak
- \fi
- \strut % new, needed below
- \dostarttagged\t!delimitedsymbol\empty
- \dotagsetdelimitedsymbol\s!middle
- \delimitedtextparameter#1% unhbox\scratchbox
- \dostoptagged
- % \penalty\plustenthousand % else overfull boxes, but that's better than dangling periods
- \kern\d_typo_delimited_signal % +- \prewordbreak
- \fi
- \endgroup
- \typo_delimited_start_content}
+ \endgroup
+ \else
+ \settrue\c_typo_delimited_repeating
+ \fi}
\def\typo_delimited_handle_left#1%
{\begingroup
@@ -717,11 +749,11 @@
\unskip
\hskip\hspaceamount\currentusedlanguage{interquotation}%
\fi\fi
- \strut % new, needed below
- \ifhmode % else funny pagebeaks
- \penalty\plustenthousand
- \hskip\zeropoint % == \prewordbreak
- \fi
+ % \strut % new, needed below
+ % \ifhmode % else funny pagebeaks
+ % \penalty\plustenthousand
+ % \hskip\zeropoint % == \prewordbreak
+ % \fi
\strut % new, needed below
\dostarttagged\t!delimitedsymbol\empty
\dotagsetdelimitedsymbol\s!left
diff --git a/tex/context/base/mkiv/typo-dha.lua b/tex/context/base/mkiv/typo-dha.lua
index af01f0f0d..c0bbdc396 100644
--- a/tex/context/base/mkiv/typo-dha.lua
+++ b/tex/context/base/mkiv/typo-dha.lua
@@ -41,13 +41,11 @@ if not modules then modules = { } end modules ['typo-dha'] = {
local nodes, node = nodes, node
-local trace_directions = false trackers.register("typesetters.directions.default", function(v) trace_directions = v end)
+local trace_directions = false trackers.register("typesetters.directions", function(v) trace_directions = v end)
local report_directions = logs.reporter("typesetting","text directions")
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local getnext = nuts.getnext
local getprev = nuts.getprev
@@ -57,7 +55,7 @@ local getsubtype = nuts.getsubtype
local getlist = nuts.getlist
local getattr = nuts.getattr
local getprop = nuts.getprop
-local getdir = nuts.getdir
+local getdirection = nuts.getdirection
local isglyph = nuts.isglyph -- or ischar
local setprop = nuts.setprop
@@ -71,7 +69,7 @@ local end_of_math = nuts.end_of_math
local nodepool = nuts.pool
local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
+local gluecodes = nodes.gluecodes
local glyph_code = nodecodes.glyph
local math_code = nodecodes.math
@@ -80,9 +78,13 @@ local glue_code = nodecodes.glue
local dir_code = nodecodes.dir
local localpar_code = nodecodes.localpar
-local parfillskip_code = skipcodes.parfillskip
+local dirvalues = nodes.dirvalues
+local lefttoright_code = dirvalues.lefttoright
+local righttoleft_code = dirvalues.righttoleft
-local new_textdir = nodepool.textdir
+local parfillskip_code = gluecodes.parfillskip
+
+local new_direction = nodepool.direction
local insert = table.insert
@@ -104,14 +106,14 @@ local strip = false
local s_isol = fonts.analyzers.states.isol
-local function stopdir(finish)
- local n = new_textdir(finish == "TRT" and "-TRT" or "-TLT")
+local function stopdir(finish) -- we could use finish directly
+ local n = new_direction(finish == righttoleft_code and righttoleft_code or lefttoright_code,true)
setprop(n,"direction",true)
return n
end
-local function startdir(finish)
- local n = new_textdir(finish == "TRT" and "+TRT" or "+TLT")
+local function startdir(finish) -- we could use finish directly
+ local n = new_direction(finish == righttoleft_code and righttoleft_code or lefttoright_code)
setprop(n,"direction",true)
return n
end
@@ -136,7 +138,7 @@ end
local function process(start)
- local head = tonut(start) -- we have a global head
+ local head = start
local current = head
local autodir = 0
local embedded = 0
@@ -309,27 +311,31 @@ local function process(start)
elseif id == kern_code then
setprop(current,"direction",'k')
elseif id == dir_code then
- local dir = getdir(current)
- if dir == "+TRT" then
- autodir = -1
- elseif dir == "+TLT" then
- autodir = 1
- elseif dir == "-TRT" or dir == "-TLT" then
- if embedded and embedded~= 0 then
+ local direction, pop = getdirection(current)
+ if direction == righttoleft_code then
+ if not pop then
+ autodir = -1
+ elseif embedded and embedded~= 0 then
+ autodir = embedded
+ else
+ autodir = 0
+ end
+ elseif direction == lefttoright_code then
+ if not pop then
+ autodir = 1
+ elseif embedded and embedded~= 0 then
autodir = embedded
else
autodir = 0
end
- else
- -- message
end
textdir = autodir
setprop(current,"direction",true)
- elseif id == localpar_code then
- local dir = getdir(current)
- if dir == 'TRT' then
+ elseif id == localpar_code and getsubtype(current) == 0 then
+ local direction = getdirection(current)
+ if direction == righttoleft_code then
autodir = -1
- elseif dir == 'TLT' then
+ elseif direction == lefttoright_code then
autodir = 1
end
pardir = autodir
@@ -443,7 +449,7 @@ local function process(start)
end
end
- return tonode(head), done
+ return head
end
diff --git a/tex/context/base/mkiv/typo-dig.lua b/tex/context/base/mkiv/typo-dig.lua
index 61e96c6b6..175fc0cc7 100644
--- a/tex/context/base/mkiv/typo-dig.lua
+++ b/tex/context/base/mkiv/typo-dig.lua
@@ -20,15 +20,12 @@ local report_digits = logs.reporter("typesetting","digits")
local nodes, node = nodes, node
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local getnext = nuts.getnext
local getprev = nuts.getprev
-local getfont = nuts.getfont
-local getchar = nuts.getchar
local getid = nuts.getid
local getwidth = nuts.getwidth
+local isglyph = nuts.isglyph
local takeattr = nuts.takeattr
local setlink = nuts.setlink
@@ -99,8 +96,7 @@ function nodes.aligned(head,start,stop,width,how)
end
actions[1] = function(head,start,attr)
- local font = getfont(start)
- local char = getchar(start)
+ local char, font = isglyph(start)
local unic = chardata[font][char].unicode or char
if charbase[unic].category == "nd" then -- ignore unic tables
local oldwidth = getwidth(start)
@@ -111,23 +107,21 @@ actions[1] = function(head,start,attr)
attr%100,div(attr,100),char,unic,newwidth-oldwidth)
end
head, start = nodes.aligned(head,start,start,newwidth,"middle")
- return head, start, true
+ return head, start
end
end
- return head, start, false
+ return head, start
end
function digits.handler(head)
- head = tonut(head)
- local done, current, ok = false, head, false
+ local current = head
while current do
if getid(current) == glyph_code then
local attr = takeattr(current,a_digits)
if attr and attr > 0 then
local action = actions[attr%100] -- map back to low number
if action then
- head, current, ok = action(head,current,attr)
- done = done and ok
+ head, current = action(head,current,attr)
elseif trace_digits then
report_digits("unknown digit trigger %a",attr)
end
@@ -137,7 +131,7 @@ function digits.handler(head)
current = getnext(current)
end
end
- return tonode(head), done
+ return head
end
local m, enabled = 0, false -- a trick to make neighbouring ranges work
diff --git a/tex/context/base/mkiv/typo-dir.lua b/tex/context/base/mkiv/typo-dir.lua
index 7fbf5f6d3..88c84bd02 100644
--- a/tex/context/base/mkiv/typo-dir.lua
+++ b/tex/context/base/mkiv/typo-dir.lua
@@ -45,8 +45,9 @@ local band = bit32.band
local texsetattribute = tex.setattribute
local unsetvalue = attributes.unsetvalue
-local getnext = nodes.getnext
-local getattr = nodes.getattr
+local nuts = nodes.nuts
+local getnext = nuts.getnext
+local getattr = nuts.getattr
local enableaction = nodes.tasks.enableaction
local tracers = nodes.tracers
@@ -165,24 +166,24 @@ local stoptiming = statistics.stoptiming
--
-- \enabledirectives[typesetters.directions.onetoo]
-function directions.handler(head,_,_,_,direction)
+function directions.handler(head,where,_,_,direction)
local only_one = not getnext(head)
if only_one and not one_too then
- return head, false
+ return head
end
local attr = getattr(head,a_directions)
if not attr or attr == 0 then
- return head, false
+ return head
end
local method = getmethod(attr)
local handler = handlers[method]
if not handler then
- return head, false
+ return head
end
starttiming(directions)
- local head, done = handler(head,direction,only_one)
+ head = handler(head,direction,only_one,where)
stoptiming(directions)
- return head, done
+ return head
end
statistics.register("text directions", function()
diff --git a/tex/context/base/mkiv/typo-dir.mkiv b/tex/context/base/mkiv/typo-dir.mkiv
index d92c93793..7449a7053 100644
--- a/tex/context/base/mkiv/typo-dir.mkiv
+++ b/tex/context/base/mkiv/typo-dir.mkiv
@@ -18,17 +18,13 @@
\unprotect
-\registerctxluafile{typo-dir}{}
+\registerctxluafile{typo-dir}{optimize}
\registerctxluafile{typo-dha}{}
-\registerctxluafile{typo-dua}{}
-\registerctxluafile{typo-dub}{}
-\doifelsefileexists{typo-duc-new.lua} {
- \registerctxluafile{typo-duc-new}{}
-} {
- \registerctxluafile{typo-duc}{}
-}
+%registerctxluafile{typo-dua}{}
+%registerctxluafile{typo-dub}{}
+\registerctxluafile{typo-duc}{}
-\definesystemattribute[directions][public]
+\definesystemattribute[directions][public,pickup]
\installcorenamespace{directions}
\installcorenamespace{directionsbidimode}
@@ -69,8 +65,9 @@
\expandafter\glet\csname\??directionsbidimode\currentbidistamp\endcsname\currentbidimode}
\appendtoks
+ \edef\p_bidi{\directionsparameter\c!bidi}%
\edef\currentbidistamp
- {\directionsparameter\c!bidi
+ {\p_bidi
:\directionsparameter\c!method
:\directionsparameter\c!fences}%
\expandafter\let\expandafter\currentbidimode\csname\??directionsbidimode\currentbidistamp\endcsname
@@ -83,6 +80,11 @@
\else
\setdirection[\number\directionsbidimode]%
\fi
+ \ifx\p_bidi\v!global
+ \pickupdirectionsattribute
+ \else
+ \forgetdirectionsattribute
+ \fi
\to \everysetupdirections
\appendtoks
@@ -104,8 +106,8 @@
\unexpanded\edef\bidilro{\normalUchar"202D}
\unexpanded\edef\bidirlo{\normalUchar"202E}
-\unexpanded\def\dirlre{\ifcase\directionsbidimode\or\bidilre\or\textdir TLT\fi}
-\unexpanded\def\dirrle{\ifcase\directionsbidimode\or\bidirle\or\textdir TRT\fi}
+\unexpanded\def\dirlre{\ifcase\directionsbidimode\or\bidilre\or\textdirection\directionlefttoright\fi}
+\unexpanded\def\dirrle{\ifcase\directionsbidimode\or\bidirle\or\textdirection\directionrighttoleft\fi}
\unexpanded\def\dirlro{\ifcase\directionsbidimode\or\bidilro\or\setdirection[3]\fi}
\unexpanded\def\dirrlo{\ifcase\directionsbidimode\or\bidirlo\or\setdirection[4]\fi}
@@ -121,85 +123,85 @@
% bidi test
-\definefontfeature
- [arab]
- [mode=node,language=dflt,script=arab,
- init=yes,medi=yes,fina=yes,isol=yes,
- liga=yes,dlig=yes,rlig=yes,clig=yes,
- mark=yes,mkmk=yes,kern=yes,curs=yes]
-
-\font\Arabic=arabtype*arab at 20pt
-
-\def\LATIN{LATIN} {\setdirection[1]} % enable this
-\def\ARAB {محمد}
-
-\startluacode
- function documentdata.split_tokens(str)
- for s in str:bytes() do
- context.sprint(tex.ctxcatcodes,string.format("\\hbox{\\char %s}",s))
- end
- end
-\stopluacode
-
-\unexpanded\def\biditest#1#2#3% font text raw
- {\dontleavehmode\hbox
- {\framed[offset=overlay]{\tttf#2}\quad
- \enabletrackers[typesetters.directions]%
- \framed[offset=overlay]{#1#3}\quad
- \disabletrackers[typesetters.directions]%
- \tttf\ctxlua{documentdata.split_tokens([[\detokenize{#3}]])}}}
-
-\startbuffer[bidi-sample]
-\biditest\Arabic{LATIN BARA}{\textdir TLT\relax \LATIN\ \ARAB}\par
-\biditest\Arabic{BARA LATIN}{\textdir TRT\relax \LATIN\ \ARAB}\par
-\biditest\Arabic{LATIN ARAB}{\textdir TLT{\bidilro \LATIN\ \ARAB}}\par % right -> left
-\biditest\Arabic{LATIN ARAB}{\textdir TRT{\bidilro \LATIN\ \ARAB}}\par % right -> left
-\biditest\Arabic{BARA NITAL}{\textdir TLT{\bidirlo \LATIN\ \ARAB}}\par % left -> right
-\biditest\Arabic{BARA NITAL}{\textdir TRT{\bidirlo \LATIN\ \ARAB}}\par % left -> right
-\stopbuffer
-
-\startbuffer[bidi-sample]
-\biditest\Arabic{LATIN BARA}{\textdir TLT\relax \LATIN\ \ARAB}\par
-\biditest\Arabic{BARA LATIN}{\textdir TRT\relax \LATIN\ \ARAB}\par
-\biditest\Arabic{LATIN ARAB}{\textdir TLT\bidilro \LATIN\ \ARAB}\par % right -> left
-\biditest\Arabic{LATIN ARAB}{\textdir TRT\bidilro \LATIN\ \ARAB}\par % right -> left
-\biditest\Arabic{BARA NITAL}{\textdir TLT\bidirlo \LATIN\ \ARAB}\par % left -> right
-\biditest\Arabic{BARA NITAL}{\textdir TRT\bidirlo \LATIN\ \ARAB}\par % left -> right
-\stopbuffer
-
-\startbuffer[bidi-setup]
-\setupdirections[bidi=off]
-\stopbuffer
-
-{\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]}
-
-\startbuffer[bidi-setup]
-\setupdirections[bidi=global]
-\stopbuffer
-
-{\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]}
-
-\startbuffer[bidi-setup]
-\setupdirections[bidi=local]
-\stopbuffer
-
-{\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]}
-
-\startbuffer[bidi-sample]
-\setupdirections[bidi=global]
-
- \hbox{\righttoleft\arabicfont (0001)}\par
- \dontleavehmode\hbox{\righttoleft\arabicfont (0002)}\par
- {\righttoleft\arabicfont (0003)\par}
- {\righttoleft\arabicfont (0004)}\par
- \dontleavehmode{\righttoleft\arabicfont (0005)\par}
- \dontleavehmode{\righttoleft\arabicfont (0006)}\par
- \rtlhbox{\arabicfont (0007)}\par
- \ltrhbox{\arabicfont (0008)}\par
-\dontleavehmode\rtlhbox{\arabicfont (0009)}\par
-\dontleavehmode\ltrhbox{\arabicfont (0010)}\par
-\stopsetups
-
-{\typebuffer[bidi-sample] \getbuffer[bidi-sample]}
-
-\stoptext
+% \definefontfeature
+% [arab]
+% [mode=node,language=dflt,script=arab,
+% init=yes,medi=yes,fina=yes,isol=yes,
+% liga=yes,dlig=yes,rlig=yes,clig=yes,
+% mark=yes,mkmk=yes,kern=yes,curs=yes]
+%
+% \font\Arabic=arabtype*arab at 20pt
+%
+% \def\LATIN{LATIN} {\setdirection[1]} % enable this
+% \def\ARAB {عربي}
+%
+% \startluacode
+% function documentdata.split_tokens(str)
+% for s in str:bytes() do
+% context.sprint(tex.ctxcatcodes,string.format("\\hbox{\\char %s}",s))
+% end
+% end
+% \stopluacode
+%
+% \unexpanded\def\biditest#1#2#3% font text raw
+% {\dontleavehmode\hbox
+% {\framed[offset=overlay]{\tttf#2}\quad
+% \enabletrackers[typesetters.directions]%
+% \framed[offset=overlay]{#1#3}\quad
+% \disabletrackers[typesetters.directions]%
+% \tttf\ctxlua{documentdata.split_tokens([[\detokenize{#3}]])}}}
+%
+% \startbuffer[bidi-sample]
+% \biditest\Arabic{LATIN BARA}{\lefttoright\relax \LATIN\ \ARAB}\par
+% \biditest\Arabic{BARA LATIN}{\righttoleft\relax \LATIN\ \ARAB}\par
+% \biditest\Arabic{LATIN ARAB}{\lefttoright{\bidilro \LATIN\ \ARAB}}\par % right -> left
+% \biditest\Arabic{LATIN ARAB}{\righttoleft{\bidilro \LATIN\ \ARAB}}\par % right -> left
+% \biditest\Arabic{BARA NITAL}{\lefttoright{\bidirlo \LATIN\ \ARAB}}\par % left -> right
+% \biditest\Arabic{BARA NITAL}{\righttoleft{\bidirlo \LATIN\ \ARAB}}\par % left -> right
+% \stopbuffer
+%
+% \startbuffer[bidi-sample]
+% \biditest\Arabic{LATIN BARA}{\lefttoright\relax \LATIN\ \ARAB}\par
+% \biditest\Arabic{BARA LATIN}{\righttoleft\relax \LATIN\ \ARAB}\par
+% \biditest\Arabic{LATIN ARAB}{\lefttoright\bidilro \LATIN\ \ARAB}\par % right -> left
+% \biditest\Arabic{LATIN ARAB}{\righttoleft\bidilro \LATIN\ \ARAB}\par % right -> left
+% \biditest\Arabic{BARA NITAL}{\lefttoright\bidirlo \LATIN\ \ARAB}\par % left -> right
+% \biditest\Arabic{BARA NITAL}{\righttoleft\bidirlo \LATIN\ \ARAB}\par % left -> right
+% \stopbuffer
+%
+% \startbuffer[bidi-setup]
+% \setupdirections[bidi=off]
+% \stopbuffer
+%
+% {\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]}
+%
+% \startbuffer[bidi-setup]
+% \setupdirections[bidi=global]
+% \stopbuffer
+%
+% {\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]}
+%
+% \startbuffer[bidi-setup]
+% \setupdirections[bidi=local]
+% \stopbuffer
+%
+% {\typebuffer[bidi-setup] \getbuffer[bidi-setup] \getbuffer[bidi-sample]}
+%
+% \startbuffer[bidi-sample]
+% \setupdirections[bidi=global]
+%
+% \hbox{\righttoleft\arabicfont (0001)}\par
+% \dontleavehmode\hbox{\righttoleft\arabicfont (0002)}\par
+% {\righttoleft\arabicfont (0003)\par}
+% {\righttoleft\arabicfont (0004)}\par
+% \dontleavehmode{\righttoleft\arabicfont (0005)\par}
+% \dontleavehmode{\righttoleft\arabicfont (0006)}\par
+% \rtlhbox{\arabicfont (0007)}\par
+% \ltrhbox{\arabicfont (0008)}\par
+% \dontleavehmode\rtlhbox{\arabicfont (0009)}\par
+% \dontleavehmode\ltrhbox{\arabicfont (0010)}\par
+% \stopsetups
+%
+% {\typebuffer[bidi-sample] \getbuffer[bidi-sample]}
+%
+% \stoptext
diff --git a/tex/context/base/mkiv/typo-drp.lua b/tex/context/base/mkiv/typo-drp.lua
index 1e142280f..9a59891e1 100644
--- a/tex/context/base/mkiv/typo-drp.lua
+++ b/tex/context/base/mkiv/typo-drp.lua
@@ -28,14 +28,11 @@ local enableaction = tasks.enableaction
local disableaction = tasks.disableaction
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local getnext = nuts.getnext
local getprev = nuts.getprev
local getchar = nuts.getchar
local getid = nuts.getid
-local getsubtype = nuts.getsubtype
local getattr = nuts.getattr
local getwhd = nuts.getwhd
@@ -59,8 +56,9 @@ local new_kern = nodepool.kern
local insert_before = nuts.insert_before
local insert_after = nuts.insert_after
local remove_node = nuts.remove
-local traverse_id = nuts.traverse_id
-local traverse = nuts.traverse
+
+local nextnode = nuts.traversers.node
+local nextglyph = nuts.traversers.glyph
local variables = interfaces.variables
local v_default = variables.default
@@ -139,9 +137,8 @@ interfaces.implement {
-- a page so this has a low priority
actions[v_default] = function(head,setting)
- local done = false
local id = getid(head)
- if id == localpar_code then
+ if id == localpar_code then -- and getsubtype(head) == 0
-- begin of par
local first = getnext(head)
local indent = false
@@ -173,7 +170,7 @@ actions[v_default] = function(head,setting)
-- 1 char | n chars | skip first quote | ignore punct | keep punct
--
if getattr(first,a_initial) then
- for current in traverse(getnext(first)) do
+ for current in nextnode, getnext(first) do
if getattr(current,a_initial) then
last = current
else
@@ -189,10 +186,10 @@ actions[v_default] = function(head,setting)
local next = getnext(first)
if not next then
-- don't start with a quote or so
- return head, false
+ return head
end
last = nil
- for current in traverse_id(glyph_code,next) do
+ for current in nextglyph, next do
head, first = remove_node(head,first,true)
first = current
last = first
@@ -200,21 +197,21 @@ actions[v_default] = function(head,setting)
end
if not last then
-- no following glyph or so
- return head, false
+ return head
end
else
-- keep quote etc with initial
local next = getnext(first)
if not next then
-- don't start with a quote or so
- return head, false
+ return head
end
- for current in traverse_id(glyph_code,next) do
+ for current in nextglyph, next do
last = current
break
end
if last == first then
- return head, false
+ return head
end
end
elseif kind == "pf" then
@@ -225,8 +222,7 @@ actions[v_default] = function(head,setting)
-- maybe also: get all A. B. etc
local next = getnext(first)
if next then
- for current in traverse_id(glyph_code,next) do
- local char = getchar(current)
+ for current, char in nextglyph, next do
local kind = category(char)
if kind == "po" then
if method[v_last] then
@@ -241,7 +237,7 @@ actions[v_default] = function(head,setting)
end
end
else
- for current in traverse_id(glyph_code,first) do
+ for current in nextglyph, first do
last = current
if length <= 1 then
break
@@ -265,12 +261,12 @@ actions[v_default] = function(head,setting)
end
-- apply font
--- local g = nodes.copy(tonode(current))
+-- local g = nuts.copy(current)
-- g.subtype = 0
-- nodes.handlers.characters(g)
-- nodes.handlers.protectglyphs(g)
-- setchar(current,g.char)
--- nodes.flush_node(g)
+-- nuts.flush_node(g)
-- can be a helper
if ca and ca > 0 then
@@ -319,7 +315,7 @@ actions[v_default] = function(head,setting)
end
--
local hoffset = width + hoffset + distance + (indent and parindent or 0)
- for current in traverse_id(glyph_code,first) do
+ for current in nextglyph, first do
setoffsets(current,-hoffset,-voffset) -- no longer - height here
if current == last then
break
@@ -347,14 +343,12 @@ actions[v_default] = function(head,setting)
if indent then
insert_after(first,first,new_kern(-parindent))
end
- done = true
end
end
- return head, done
+ return head
end
function initials.handler(head)
- head = tonut(head)
local start = head
local attr = nil
while start do
@@ -377,9 +371,8 @@ function initials.handler(head)
if trace_initials then
report_initials("processing initials, alternative %a",alternative)
end
- local head, done = action(head,settings)
- return tonode(head), done
+ return action(head,settings)
end
end
- return tonode(head), false
+ return head
end
diff --git a/tex/context/base/mkiv/typo-drp.mkiv b/tex/context/base/mkiv/typo-drp.mkiv
index 371ea38d6..183925108 100644
--- a/tex/context/base/mkiv/typo-drp.mkiv
+++ b/tex/context/base/mkiv/typo-drp.mkiv
@@ -118,7 +118,7 @@
\kern\zeropoint % we need a node
\p_text
\endgroup
- \globallet\typo_initial_handle\relax}
+ \glet\typo_initial_handle\relax}
\let\typo_initial_handle\relax
diff --git a/tex/context/base/mkiv/typo-dua.lua b/tex/context/base/mkiv/typo-dua.lua
index 1e48dfb91..3db5f510a 100644
--- a/tex/context/base/mkiv/typo-dua.lua
+++ b/tex/context/base/mkiv/typo-dua.lua
@@ -68,8 +68,6 @@ local directiondata = characters.directions
local mirrordata = characters.mirrors
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local getnext = nuts.getnext
local getid = nuts.getid
@@ -77,11 +75,11 @@ local getsubtype = nuts.getsubtype
local getlist = nuts.getlist
local getchar = nuts.getchar
local getprop = nuts.getprop
-local getdir = nuts.getdir
+local getdirection = nuts.getdirection
local setprop = nuts.setprop
local setchar = nuts.setchar
-local setdir = nuts.setdir
+local setdirection = nuts.setdirection
----- setattrlist = nuts.setattrlist
local remove_node = nuts.remove
@@ -89,10 +87,10 @@ local insert_node_after = nuts.insert_after
local insert_node_before = nuts.insert_before
local nodepool = nuts.pool
-local new_textdir = nodepool.textdir
+local new_direction = nodepool.direction
local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
+local gluecodes = nodes.gluecodes
local glyph_code = nodecodes.glyph
local glue_code = nodecodes.glue
@@ -101,23 +99,28 @@ local vlist_code = nodecodes.vlist
local math_code = nodecodes.math
local dir_code = nodecodes.dir
local localpar_code = nodecodes.localpar
-local parfillskip_code = skipcodes.parfillskip
------ object_replacement = 0xFFFC -- object replacement character
-local maximum_stack = 60 -- probably spec but not needed
+local parfillskip_code = gluecodes.parfillskip
+
+local dirvalues = nodes.dirvalues
+local lefttoright_code = dirvalues.lefttoright
+local righttoleft_code = dirvalues.righttoleft
+
+local maximum_stack = 60
local directions = typesetters.directions
local setcolor = directions.setcolor
------ a_directions = attributes.private('directions')
-
local remove_controls = true directives.register("typesetters.directions.one.removecontrols",function(v) remove_controls = v end)
-local trace_directions = false trackers .register("typesetters.directions.one", function(v) trace_directions = v end)
-local trace_details = false trackers .register("typesetters.directions.one.details", function(v) trace_details = v end)
-
local report_directions = logs.reporter("typesetting","directions one")
+local trace_directions = false trackers .register("typesetters.directions", function(v) trace_directions = v end)
+local trace_details = false trackers .register("typesetters.directions.details", function(v) trace_details = v end)
+
+
+
+
local whitespace = {
lre = true,
rle = true,
@@ -234,13 +237,19 @@ local function build_list(head) -- todo: store node pointer ... saves loop
list[size] = { char = 0x0020, direction = "ws", original = "ws", level = 0 }
current = getnext(current)
elseif id == dir_code then
- local dir = getdir(current)
- if dir == "+TLT" then
- list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 }
- elseif dir == "+TRT" then
- list[size] = { char = 0x202B, direction = "rle", original = "rle", level = 0 }
- elseif dir == "-TLT" or dir == "-TRT" then
- list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 }
+ local direction, pop = getdirection(current)
+ if direction == lefttoright_code then
+ if pop then
+ list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 }
+ else
+ list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 }
+ end
+ elseif direction == righttoleft_code then
+ if pop then
+ list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 }
+ else
+ list[size] = { char = 0x202B, direction = "rle", original = "rle", level = 0 }
+ end
else
list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, id = id } -- object replacement character
end
@@ -323,27 +332,33 @@ local function find_run_limit_b_s_ws_on(list,start,limit)
return start
end
-local function get_baselevel(head,list,size) -- todo: skip if first is object (or pass head and test for localpar)
- local id = getid(head)
- if id == localpar_code then
- if getdir(head) == "TRT" then
- return 1, "TRT", true
- else
- return 0, "TLT", true
+local function get_baselevel(head,list,size,direction)
+ -- This is an adapted version:
+ if direction == lefttoright_code or direction == righttoleft_code then
+ return direction, true
+ elseif getid(head) == localpar_code and getsubtype(head) == 0 then
+ direction = getdirection(head)
+ if direction == lefttoright_code or direction == righttoleft_code then
+ return direction, true
end
- else
- -- P2, P3
- for i=1,size do
- local entry = list[i]
- local direction = entry.direction
- if direction == "r" or direction == "al" then
- return 1, "TRT", true
- elseif direction == "l" then
- return 0, "TLT", true
- end
+ end
+ -- for old times sake we we handle strings too
+ if direction == "TLT" then
+ return lefttoright_code, true
+ elseif direction == "TRT" then
+ return righttoleft_code, true
+ end
+ -- P2, P3
+ for i=1,size do
+ local entry = list[i]
+ local direction = entry.direction
+ if direction == "r" or direction == "al" then
+ return righttoleft_code, true
+ elseif direction == "l" then
+ return lefttoright_code, true
end
- return 0, "TLT", false
end
+ return lefttoright_code, false
end
local function resolve_explicit(list,size,baselevel)
@@ -409,7 +424,7 @@ local function resolve_explicit(list,size,baselevel)
end
-- X7
elseif direction == "pdf" then
- if nofstack < maximum_stack then
+ if noifstack > 0 then
local stacktop = stack[nofstack]
nofstack = nofstack - 1
level = stacktop[1]
@@ -418,7 +433,7 @@ local function resolve_explicit(list,size,baselevel)
entry.direction = "bn"
entry.remove = true
elseif trace_directions then
- report_directions("stack overflow at position %a with direction %a",i,direction)
+ report_directions("stack underflow at position %a with direction %a",i,direction)
end
-- X6
else
@@ -679,8 +694,6 @@ local function resolve_levels(list,size,baselevel)
end
end
--- This is not ok but we keep it as-is:
-
local function insert_dir_points(list,size)
-- L2, but no actual reversion is done, we simply annotate where
-- begindir/endddir node will be inserted.
@@ -697,11 +710,11 @@ local function insert_dir_points(list,size)
local begindir = nil
local enddir = nil
if level % 2 == 1 then
- begindir = "+TRT"
- enddir = "-TRT"
+ begindir = righttoleft_code
+ enddir = righttoleft_code
else
- begindir = "+TLT"
- enddir = "-TLT"
+ begindir = lefttoright_code
+ enddir = lefttoright_code
end
for i=1,size do
local entry = list[i]
@@ -730,7 +743,6 @@ end
local function apply_to_list(list,size,head,pardir)
local index = 1
local current = head
- local done = false
while current do
if index > size then
report_directions("fatal error, size mismatch")
@@ -751,34 +763,31 @@ local function apply_to_list(list,size,head,pardir)
setcolor(current,direction,false,mirror)
end
elseif id == hlist_code or id == vlist_code then
- setdir(current,pardir) -- is this really needed?
+ setdirection(current,pardir) -- is this really needed?
elseif id == glue_code then
if enddir and getsubtype(current) == parfillskip_code then
-- insert the last enddir before \parfillskip glue
- local d = new_textdir(enddir)
- setprop(d,"directions",true)
+ local d = new_direction(enddir,true)
+ -- setprop(d,"directions",true)
-- setattrlist(d,current)
head = insert_node_before(head,current,d)
enddir = false
- done = true
end
elseif begindir then
- if id == localpar_code then
+ if id == localpar_code and getsubtype(current) == 0 then
-- localpar should always be the 1st node
- local d = new_textdir(begindir)
- setprop(d,"directions",true)
+ local d = new_direction(begindir)
+ -- setprop(d,"directions",true)
-- setattrlist(d,current)
head, current = insert_node_after(head,current,d)
begindir = nil
- done = true
end
end
if begindir then
- local d = new_textdir(begindir)
- setprop(d,"directions",true)
+ local d = new_direction(begindir)
+ -- setprop(d,"directions",true)
-- setattrlist(d,current)
head = insert_node_before(head,current,d)
- done = true
end
local skip = entry.skip
if skip and skip > 0 then
@@ -788,30 +797,28 @@ local function apply_to_list(list,size,head,pardir)
end
end
if enddir then
- local d = new_textdir(enddir)
- setprop(d,"directions",true)
+ local d = new_direction(enddir,true)
+ -- setprop(d,"directions",true)
-- setattrlist(d,current)
head, current = insert_node_after(head,current,d)
- done = true
end
if not entry.remove then
current = getnext(current)
elseif remove_controls then
-- X9
head, current = remove_node(head,current,true)
- done = true
else
current = getnext(current)
end
index = index + 1
end
- return head, done
+ return head
end
-local function process(head)
- head = tonut(head)
+local function process(head,direction,only_one,where)
+ -- This is an adapted version:
local list, size = build_list(head)
- local baselevel, pardir, dirfound = get_baselevel(head,list,size) -- we always have an inline dir node in context
+ local baselevel, dirfound = get_baselevel(head,list,size,direction)
if not dirfound and trace_details then
report_directions("no initial direction found, gambling")
end
@@ -825,8 +832,7 @@ local function process(head)
report_directions("after : %s",show_list(list,size,"direction"))
report_directions("result : %s",show_done(list,size))
end
- local head, done = apply_to_list(list,size,head,pardir)
- return tonode(head), done
+ return apply_to_list(list,size,head,baselevel)
end
directions.installhandler(interfaces.variables.one,process)
diff --git a/tex/context/base/mkiv/typo-dub.lua b/tex/context/base/mkiv/typo-dub.lua
index d0747ae6c..f27e40476 100644
--- a/tex/context/base/mkiv/typo-dub.lua
+++ b/tex/context/base/mkiv/typo-dub.lua
@@ -55,8 +55,6 @@ local mirrordata = characters.mirrors
local textclassdata = characters.textclasses
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local getnext = nuts.getnext
local getid = nuts.getid
@@ -65,11 +63,11 @@ local getlist = nuts.getlist
local getchar = nuts.getchar
local getattr = nuts.getattr
local getprop = nuts.getprop
-local getdir = nuts.getdir
+local getdirection = nuts.getdirection
local setprop = nuts.setprop
local setchar = nuts.setchar
-local setdir = nuts.setdir
+local setdirection = nuts.setdirection
local setattrlist = nuts.setattrlist
local remove_node = nuts.remove
@@ -77,10 +75,10 @@ local insert_node_after = nuts.insert_after
local insert_node_before = nuts.insert_before
local nodepool = nuts.pool
-local new_textdir = nodepool.textdir
+local new_direction = nodepool.direction
local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
+local gluecodes = nodes.gluecodes
local glyph_code = nodecodes.glyph
local glue_code = nodecodes.glue
@@ -89,24 +87,29 @@ local vlist_code = nodecodes.vlist
local math_code = nodecodes.math
local dir_code = nodecodes.dir
local localpar_code = nodecodes.localpar
-local parfillskip_code = skipcodes.parfillskip
-local maximum_stack = 0xFF -- unicode: 60, will be jumped to 125, we don't care too much
+local parfillskip_code = gluecodes.parfillskip
+
+local dirvalues = nodes.dirvalues
+local lefttoright_code = dirvalues.lefttoright
+local righttoleft_code = dirvalues.righttoleft
+
+local maximum_stack = 0xFF
+
+local a_directions = attributes.private('directions')
local directions = typesetters.directions
local setcolor = directions.setcolor
local getfences = directions.getfences
-local a_directions = attributes.private('directions')
-
local remove_controls = true directives.register("typesetters.directions.removecontrols",function(v) remove_controls = v end)
----- analyze_fences = true directives.register("typesetters.directions.analyzefences", function(v) analyze_fences = v end)
-local trace_directions = false trackers .register("typesetters.directions.two", function(v) trace_directions = v end)
-local trace_details = false trackers .register("typesetters.directions.two.details", function(v) trace_details = v end)
-local trace_list = false trackers .register("typesetters.directions.two.list", function(v) trace_list = v end)
+local report_directions = logs.reporter("typesetting","directions three")
-local report_directions = logs.reporter("typesetting","directions two")
+local trace_directions = false trackers.register("typesetters.directions", function(v) trace_directions = v end)
+local trace_details = false trackers.register("typesetters.directions.details", function(v) trace_details = v end)
+local trace_list = false trackers.register("typesetters.directions.list", function(v) trace_list = v end)
-- strong (old):
--
@@ -117,7 +120,7 @@ local report_directions = logs.reporter("typesetting","directions two")
-- lre : left to right embedding
-- rle : left to left embedding
-- al : right to legt arabic (esp punctuation issues)
-
+--
-- weak:
--
-- en : english number
@@ -127,23 +130,23 @@ local report_directions = logs.reporter("typesetting","directions two")
-- cs : common number separator
-- nsm : nonspacing mark
-- bn : boundary neutral
-
+--
-- neutral:
--
-- b : paragraph separator
-- s : segment separator
-- ws : whitespace
-- on : other neutrals
-
+--
-- interesting: this is indeed better (and more what we expect i.e. we already use this split
-- in the old original (also these isolates)
-
+--
-- strong (new):
--
-- l : left to right
-- r : right to left
-- al : right to left arabic (esp punctuation issues)
-
+--
-- explicit: (new)
--
-- lro : left to right override
@@ -206,27 +209,28 @@ end
local function show_done(list,size)
local joiner = utfchar(0x200C)
local result = { }
+ local format = formatters["<%s>"]
for i=1,size do
local entry = list[i]
local character = entry.char
local begindir = entry.begindir
local enddir = entry.enddir
if begindir then
- result[#result+1] = formatters["<%s>"](begindir)
+ result[#result+1] = format(begindir)
end
if entry.remove then
-- continue
elseif character == 0xFFFC then
- result[#result+1] = formatters["<%s>"]("?")
+ result[#result+1] = format("?")
elseif character == 0x0020 then
- result[#result+1] = formatters["<%s>"](" ")
+ result[#result+1] = format(" ")
elseif character >= 0x202A and character <= 0x202C then
- result[#result+1] = formatters["<%s>"](entry.original)
+ result[#result+1] = format(entry.original)
else
result[#result+1] = utfchar(character)
end
if enddir then
- result[#result+1] = formatters["<%s>"](enddir)
+ result[#result+1] = format(enddir)
end
end
return concat(result,joiner)
@@ -236,17 +240,7 @@ end
-- char is only used for mirror, so in fact we can as well only store it for
-- glyphs only
--- using metatable is slightly faster so maybe some day ...
-
--- local space = { char = 0x0020, direction = "ws", original = "ws" }
--- local lre = { char = 0x202A, direction = "lre", original = "lre" }
--- local rle = { char = 0x202B, direction = "rle", original = "rle" }
--- local pdf = { char = 0x202C, direction = "pdf", original = "pdf" }
--- local object = { char = 0xFFFC, direction = "on", original = "on" }
---
--- local t = { level = 0 } setmetatable(t,space) list[size] = t
-
-local function build_list(head) -- todo: store node pointer ... saves loop
+local function build_list(head)
-- P1
local current = head
local list = { }
@@ -282,13 +276,19 @@ local function build_list(head) -- todo: store node pointer ... saves loop
list[size] = { char = 0x0020, direction = "ws", original = "ws", level = 0 }
current = getnext(current)
elseif id == dir_code then
- local dir = getdir(current)
- if dir == "+TLT" then
- list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 }
- elseif dir == "+TRT" then
- list[size] = { char = 0x202B, direction = "rle", original = "rle", level = 0 }
- elseif dir == "-TLT" or dir == "-TRT" then
- list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 }
+ local direction, pop = getdirection(current)
+ if direction == lefttoright_code then
+ if pop then
+ list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 }
+ else
+ list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 }
+ end
+ elseif direction == righttoleft_code then
+ if pop then
+ list[size] = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 }
+ else
+ list[size] = { char = 0x202B, direction = "rle", original = "rle", level = 0 }
+ end
else
list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, id = id } -- object replacement character
end
@@ -343,8 +343,8 @@ end
local function resolve_fences(list,size,start,limit)
-- N0: funny effects, not always better, so it's an option
- local stack = { }
- local top = 0
+ local stack = { }
+ local nofstack = 0
for i=start,limit do
local entry = list[i]
if entry.direction == "on" then
@@ -355,15 +355,15 @@ local function resolve_fences(list,size,start,limit)
entry.mirror = mirror
entry.class = class
if class == "open" then
- top = top + 1
- stack[top] = { mirror, i, false }
- elseif top == 0 then
+ nofstack = nofstack + 1
+ stack[nofstack] = { mirror, i, false }
+ elseif nofstack == 0 then
-- skip
elseif class == "close" then
- while top > 0 do
- local s = stack[top]
- if s[1] == char then
- local open = s[2]
+ while nofstack > 0 do
+ local stacktop = stack[nofstack]
+ if stacktop[1] == char then
+ local open = stacktop[2]
local close = i
list[open ].paired = close
list[close].paired = open
@@ -371,7 +371,7 @@ local function resolve_fences(list,size,start,limit)
else
-- do we mirror or not
end
- top = top - 1
+ nofstack = nofstack - 1
end
end
end
@@ -394,27 +394,32 @@ end
-- the action
-local function get_baselevel(head,list,size) -- todo: skip if first is object (or pass head and test for localpar)
- local id = getid(head)
- if id == localpar_code then
- if getdir(head) == "TRT" then
- return 1, "TRT", true
- else
- return 0, "TLT", true
+local function get_baselevel(head,list,size,direction)
+ if direction == lefttoright_code or direction == righttoleft_code then
+ return direction, true
+ elseif getid(head) == localpar_code and getsubtype(head) == 0 then
+ direction = getdirection(head)
+ if direction == lefttoright_code or direction == righttoleft_code then
+ return direction, true
end
- else
- -- P2, P3
- for i=1,size do
- local entry = list[i]
- local direction = entry.direction
- if direction == "r" or direction == "al" then -- and an ?
- return 1, "TRT", true
- elseif direction == "l" then
- return 0, "TLT", true
- end
+ end
+ -- for old times sake we we handle strings too
+ if direction == "TLT" then
+ return lefttoright_code, true
+ elseif direction == "TRT" then
+ return righttoleft_code, true
+ end
+ -- P2, P3
+ for i=1,size do
+ local entry = list[i]
+ local direction = entry.direction
+ if direction == "r" or direction == "al" then -- and an ?
+ return righttoleft_code, true
+ elseif direction == "l" then
+ return lefttoright_code, true
end
- return 0, "TLT", false
end
+ return lefttoright_code, false
end
local function resolve_explicit(list,size,baselevel)
@@ -480,16 +485,17 @@ local function resolve_explicit(list,size,baselevel)
end
-- X7
elseif direction == "pdf" then
- if nofstack < maximum_stack then
+ if nofstack > 0 then
local stacktop = stack[nofstack]
- nofstack = nofstack - 1
level = stacktop[1]
override = stacktop[2]
+ nofstack = nofstack - 1
entry.level = level
entry.direction = "bn"
entry.remove = true
elseif trace_directions then
- report_directions("stack overflow at position %a with direction %a",i,direction)
+ report_directions("stack underflow at position %a with direction %a",
+ i, direction)
end
-- X6
else
@@ -688,33 +694,6 @@ local function resolve_neutral(list,size,start,limit,orderbefore,orderafter)
end
end
--- local function resolve_implicit(list,size,start,limit,orderbefore,orderafter)
--- -- I1
--- for i=start,limit do
--- local entry = list[i]
--- local level = entry.level
--- if level % 2 ~= 1 then -- not odd(level)
--- local direction = entry.direction
--- if direction == "r" then
--- entry.level = level + 1
--- elseif direction == "an" or direction == "en" then
--- entry.level = level + 2
--- end
--- end
--- end
--- -- I2
--- for i=start,limit do
--- local entry = list[i]
--- local level = entry.level
--- if level % 2 == 1 then -- odd(level)
--- local direction = entry.direction
--- if direction == "l" or direction == "en" or direction == "an" then
--- entry.level = level + 1
--- end
--- end
--- end
--- end
-
local function resolve_implicit(list,size,start,limit,orderbefore,orderafter,baselevel)
for i=start,limit do
local entry = list[i]
@@ -814,52 +793,6 @@ local function resolve_levels(list,size,baselevel,analyze_fences)
end
end
--- local function insert_dir_points(list,size)
--- -- L2, but no actual reversion is done, we simply annotate where
--- -- begindir/endddir node will be inserted.
--- local maxlevel = 0
--- local finaldir = false
--- for i=1,size do
--- local level = list[i].level
--- if level > maxlevel then
--- maxlevel = level
--- end
--- end
--- for level=0,maxlevel do
--- local started = false
--- local begindir = nil
--- local enddir = nil
--- if level % 2 == 1 then
--- begindir = "+TRT"
--- enddir = "-TRT"
--- else
--- begindir = "+TLT"
--- enddir = "-TLT"
--- end
--- for i=1,size do
--- local entry = list[i]
--- if entry.level >= level then
--- if not started then
--- entry.begindir = begindir
--- started = true
--- end
--- else
--- if started then
--- list[i-1].enddir = enddir
--- started = false
--- end
--- end
--- end
--- -- make sure to close the run at end of line
--- if started then
--- finaldir = enddir
--- end
--- end
--- if finaldir then
--- list[size].enddir = finaldir
--- end
--- end
-
local function insert_dir_points(list,size)
-- L2, but no actual reversion is done, we simply annotate where
-- begindir/endddir node will be inserted.
@@ -877,12 +810,12 @@ local function insert_dir_points(list,size)
local enddir -- = nil
local prev -- = nil
if toggle then
- begindir = "+TLT"
- enddir = "-TLT"
+ begindir = lefttoright_code
+ enddir = lefttoright_code
toggle = false
else
- begindir = "+TRT"
- enddir = "-TRT"
+ begindir = righttoleft_code
+ enddir = righttoleft_code
toggle = true
end
for i=1,size do
@@ -922,7 +855,7 @@ local function insert_dir_points(list,size)
if trace_list and n > 1 then
report_directions("unbalanced list")
end
- last.enddir = s[n] == "+TRT" and "-TRT" or "-TLT"
+ last.enddir = s[n] == righttoleft_code and righttoleft_code or lefttoright_code
end
end
end
@@ -930,7 +863,6 @@ end
local function apply_to_list(list,size,head,pardir)
local index = 1
local current = head
- local done = false
if trace_list then
report_directions("start run")
end
@@ -964,34 +896,31 @@ local function apply_to_list(list,size,head,pardir)
setcolor(current,direction,false,mirror)
end
elseif id == hlist_code or id == vlist_code then
- setdir(current,pardir) -- is this really needed?
+ setdirection(current,pardir) -- is this really needed?
elseif id == glue_code then
if enddir and getsubtype(current) == parfillskip_code then
-- insert the last enddir before \parfillskip glue
- local d = new_textdir(enddir)
- setprop(d,"directions",true)
+ local d = new_direction(enddir,true)
+ -- setprop(d,"directions",true)
-- setattrlist(d,current)
head = insert_node_before(head,current,d)
enddir = false
- done = true
end
elseif begindir then
- if id == localpar_code then
+ if id == localpar_code and getsubtype(current) == 0 then
-- localpar should always be the 1st node
- local d = new_textdir(begindir)
- setprop(d,"directions",true)
+ local d = new_direction(begindir)
+ -- setprop(d,"directions",true)
-- setattrlist(d,current)
head, current = insert_node_after(head,current,d)
begindir = nil
- done = true
end
end
if begindir then
- local d = new_textdir(begindir)
- setprop(d,"directions",true)
+ local d = new_direction(begindir)
+ -- setprop(d,"directions",true)
-- setattrlist(d,current)
head = insert_node_before(head,current,d)
- done = true
end
local skip = entry.skip
if skip and skip > 0 then
@@ -1001,18 +930,16 @@ local function apply_to_list(list,size,head,pardir)
end
end
if enddir then
- local d = new_textdir(enddir)
- setprop(d,"directions",true)
+ local d = new_direction(enddir,true)
+ -- setprop(d,"directions",true)
-- setattrlist(d,current)
head, current = insert_node_after(head,current,d)
- done = true
end
if not entry.remove then
current = getnext(current)
elseif remove_controls then
-- X9
head, current = remove_node(head,current,true)
- done = true
else
current = getnext(current)
end
@@ -1021,17 +948,16 @@ local function apply_to_list(list,size,head,pardir)
if trace_list then
report_directions("stop run")
end
- return head, done
+ return head
end
-local function process(head)
- head = tonut(head)
+local function process(head,direction,only_one,where)
-- for the moment a whole paragraph property
local attr = getattr(head,a_directions)
local analyze_fences = getfences(attr)
--
local list, size = build_list(head)
- local baselevel, pardir, dirfound = get_baselevel(head,list,size) -- we always have an inline dir node in context
+ local baselevel, dirfound = get_baselevel(head,list,size,direction)
if not dirfound and trace_details then
report_directions("no initial direction found, gambling")
end
@@ -1045,8 +971,7 @@ local function process(head)
report_directions("after : %s",show_list(list,size,"direction"))
report_directions("result : %s",show_done(list,size))
end
- local head, done = apply_to_list(list,size,head,pardir)
- return tonode(head), done
+ return apply_to_list(list,size,head,baselevel)
end
directions.installhandler(interfaces.variables.two,process)
diff --git a/tex/context/base/mkiv/typo-duc.lua b/tex/context/base/mkiv/typo-duc.lua
index 520740190..f91fc4d64 100644
--- a/tex/context/base/mkiv/typo-duc.lua
+++ b/tex/context/base/mkiv/typo-duc.lua
@@ -7,8 +7,6 @@ if not modules then modules = { } end modules ['typo-duc'] = {
comment = "Unicode bidi (sort of) variant c",
}
--- Will be replaced by typo-duc-new.lua!
-
-- This is a follow up on typo-uda which itself is a follow up on t-bidi by Khaled Hosny which
-- in turn is based on minibidi.c from Arabeyes. This is a further optimizations, as well as
-- an update on some recent unicode bidi developments. There is (and will) also be more control
@@ -58,8 +56,6 @@ local mirrordata = characters.mirrors
local textclassdata = characters.textclasses
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local getnext = nuts.getnext
local getid = nuts.getid
@@ -68,11 +64,12 @@ local getlist = nuts.getlist
local getchar = nuts.getchar
local getattr = nuts.getattr
local getprop = nuts.getprop
-local getdir = nuts.getdir
+local getdirection = nuts.getdirection
+local isglyph = nuts.isglyph
local setprop = nuts.setprop
local setchar = nuts.setchar
-local setdir = nuts.setdir
+local setdirection = nuts.setdirection
local setattrlist = nuts.setattrlist
local properties = nodes.properties.data
@@ -82,10 +79,10 @@ local insert_node_after = nuts.insert_after
local insert_node_before = nuts.insert_before
local nodepool = nuts.pool
-local new_textdir = nodepool.textdir
+local new_direction = nodepool.direction
local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
+local gluecodes = nodes.gluecodes
local glyph_code = nodecodes.glyph
local glue_code = nodecodes.glue
@@ -94,25 +91,30 @@ local vlist_code = nodecodes.vlist
local math_code = nodecodes.math
local dir_code = nodecodes.dir
local localpar_code = nodecodes.localpar
-local parfillskip_code = skipcodes.parfillskip
-local maximum_stack = 0xFF -- unicode: 60, will be jumped to 125, we don't care too much
+local parfillskip_code = gluecodes.parfillskip
+
+local dirvalues = nodes.dirvalues
+local lefttoright_code = dirvalues.lefttoright
+local righttoleft_code = dirvalues.righttoleft
+
+local maximum_stack = 0xFF
+
+local a_directions = attributes.private('directions')
local directions = typesetters.directions
local setcolor = directions.setcolor
local getfences = directions.getfences
-local a_directions = attributes.private('directions')
-
local remove_controls = true directives.register("typesetters.directions.removecontrols",function(v) remove_controls = v end)
----- analyze_fences = true directives.register("typesetters.directions.analyzefences", function(v) analyze_fences = v end)
-local trace_directions = false trackers.register("typesetters.directions.three", function(v) trace_directions = v end)
-local trace_details = false trackers.register("typesetters.directions.three.details", function(v) trace_details = v end)
-local trace_list = false trackers.register("typesetters.directions.three.list", function(v) trace_list = v end)
-
local report_directions = logs.reporter("typesetting","directions three")
+local trace_directions = false trackers.register("typesetters.directions", function(v) trace_directions = v end)
+local trace_details = false trackers.register("typesetters.directions.details", function(v) trace_details = v end)
+local trace_list = false trackers.register("typesetters.directions.list", function(v) trace_list = v end)
+
-- strong (old):
--
-- l : left to right
@@ -122,7 +124,7 @@ local report_directions = logs.reporter("typesetting","directions three")
-- lre : left to right embedding
-- rle : left to left embedding
-- al : right to legt arabic (esp punctuation issues)
-
+--
-- weak:
--
-- en : english number
@@ -132,23 +134,23 @@ local report_directions = logs.reporter("typesetting","directions three")
-- cs : common number separator
-- nsm : nonspacing mark
-- bn : boundary neutral
-
+--
-- neutral:
--
-- b : paragraph separator
-- s : segment separator
-- ws : whitespace
-- on : other neutrals
-
+--
-- interesting: this is indeed better (and more what we expect i.e. we already use this split
-- in the old original (also these isolates)
-
+--
-- strong (new):
--
-- l : left to right
-- r : right to left
-- al : right to left arabic (esp punctuation issues)
-
+--
-- explicit: (new)
--
-- lro : left to right override
@@ -241,20 +243,20 @@ end
-- keeping the list and overwriting doesn't save much runtime, only a few percent
-- char is only used for mirror, so in fact we can as well only store it for
-- glyphs only
-
+--
-- tracking what direction is used and skipping tests is not faster (extra kind of
-- compensates gain)
-local mt_space = { __index = { char = 0x0020, direction = "ws", original = "ws", level = 0 } }
-local mt_lre = { __index = { char = 0x202A, direction = "lre", original = "lre", level = 0 } }
-local mt_rle = { __index = { char = 0x202B, direction = "rle", original = "rle", level = 0 } }
-local mt_pdf = { __index = { char = 0x202C, direction = "pdf", original = "pdf", level = 0 } }
-local mt_object = { __index = { char = 0xFFFC, direction = "on", original = "on", level = 0 } }
+local mt_space = { __index = { char = 0x0020, direction = "ws", original = "ws", level = 0, skip = 0 } }
+local mt_lre = { __index = { char = 0x202A, direction = "lre", original = "lre", level = 0, skip = 0 } }
+local mt_rle = { __index = { char = 0x202B, direction = "rle", original = "rle", level = 0, skip = 0 } }
+local mt_pdf = { __index = { char = 0x202C, direction = "pdf", original = "pdf", level = 0, skip = 0 } }
+local mt_object = { __index = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = 0 } }
local stack = table.setmetatableindex("table") -- shared
local list = { } -- shared
-local function build_list(head) -- todo: store node pointer ... saves loop
+local function build_list(head,where)
-- P1
local current = head
local size = 0
@@ -263,6 +265,7 @@ local function build_list(head) -- todo: store node pointer ... saves loop
local id = getid(current)
local p = properties[current]
if p and p.directions then
+ -- tricky as dirs can be injected in between
local skip = 0
local last = id
current = getnext(current)
@@ -285,6 +288,7 @@ local function build_list(head) -- todo: store node pointer ... saves loop
elseif id == glyph_code then
local chr = getchar(current)
local dir = directiondata[chr]
+ -- could also be a metatable
list[size] = { char = chr, direction = dir, original = dir, level = 0 }
current = getnext(current)
-- if not list[dir] then list[dir] = true end -- not faster when we check for usage
@@ -292,13 +296,11 @@ local function build_list(head) -- todo: store node pointer ... saves loop
list[size] = setmetatable({ },mt_space)
current = getnext(current)
elseif id == dir_code then
- local dir = getdir(current)
- if dir == "+TLT" then
- list[size] = setmetatable({ },mt_lre)
- elseif dir == "+TRT" then
- list[size] = setmetatable({ },mt_rle)
- elseif dir == "-TLT" or dir == "-TRT" then
- list[size] = setmetatable({ },mt_pdf)
+ local dir, pop = getdirection(current)
+ if dir == lefttoright_code then
+ list[size] = setmetatable({ },pop and mt_pdf or mt_lre)
+ elseif dir == righttoleft_code then
+ list[size] = setmetatable({ },pop and mt_pdf or mt_rle)
else
list[size] = setmetatable({ id = id },mt_object)
end
@@ -351,6 +353,8 @@ end
-- ש ( ל ( א ) כ ) 2-8,4-6
-- ש ( ל [ א ] כ ) 2-8,4-6
+local fencestack = table.setmetatableindex("table")
+
local function resolve_fences(list,size,start,limit)
-- N0: funny effects, not always better, so it's an option
local nofstack = 0
@@ -365,15 +369,14 @@ local function resolve_fences(list,size,start,limit)
entry.class = class
if class == "open" then
nofstack = nofstack + 1
- local stacktop = stack[nofstack]
+ local stacktop = fencestack[nofstack]
stacktop[1] = mirror
stacktop[2] = i
- stacktop[3] = false -- not used
elseif nofstack == 0 then
-- skip
elseif class == "close" then
while nofstack > 0 do
- local stacktop = stack[nofstack]
+ local stacktop = fencestack[nofstack]
if stacktop[1] == char then
local open = stacktop[2]
local close = i
@@ -407,25 +410,31 @@ end
-- the action
local function get_baselevel(head,list,size,direction)
- if not direction and getid(head) == localpar_code then
- direction = getdir(head)
+ if direction == lefttoright_code or direction == righttoleft_code then
+ return direction, true
+ elseif getid(head) == localpar_code and getsubtype(head) == 0 then
+ direction = getdirection(head)
+ if direction == lefttoright_code or direction == righttoleft_code then
+ return direction, true
+ end
end
- if direction == "TRT" then
- return 1, "TRT", true
- elseif direction == "TLT" then
- return 0, "TLT", true
+ -- for old times sake we we handle strings too
+ if direction == "TLT" then
+ return lefttoright_code, true
+ elseif direction == "TRT" then
+ return righttoleft_code, true
end
- -- P2, P3:
+ -- P2, P3
for i=1,size do
local entry = list[i]
local direction = entry.direction
if direction == "r" or direction == "al" then -- and an ?
- return 1, "TRT", true
+ return righttoleft_code, true
elseif direction == "l" then
- return 0, "TLT", true
+ return lefttoright_code, true
end
end
- return 0, "TLT", false
+ return lefttoright_code, false
end
local function resolve_explicit(list,size,baselevel)
@@ -499,7 +508,7 @@ local function resolve_explicit(list,size,baselevel)
end
-- X7
elseif direction == "pdf" then
- if nofstack < maximum_stack then
+ if nofstack > 0 then
local stacktop = stack[nofstack]
level = stacktop[1]
override = stacktop[2]
@@ -508,7 +517,11 @@ local function resolve_explicit(list,size,baselevel)
entry.direction = "bn"
entry.remove = true
elseif trace_directions then
- report_directions("stack overflow at position %a with direction %a",i,direction)
+ report_directions("stack underflow at position %a with direction %a",
+ i, direction)
+ else
+ report_directions("stack underflow at position %a with direction %a: %s",
+ i, direction, show_list(list,size))
end
-- X6
else
@@ -518,11 +531,6 @@ local function resolve_explicit(list,size,baselevel)
end
end
end
--- else
--- for i=1,size do
--- list[i].level = baselevel
--- end
--- end
-- X8 (reset states and overrides after paragraph)
end
@@ -726,33 +734,6 @@ local function resolve_neutral(list,size,start,limit,orderbefore,orderafter)
end
end
--- local function resolve_implicit(list,size,start,limit,orderbefore,orderafter)
--- -- I1
--- for i=start,limit do
--- local entry = list[i]
--- local level = entry.level
--- if level % 2 ~= 1 then -- not odd(level)
--- local direction = entry.direction
--- if direction == "r" then
--- entry.level = level + 1
--- elseif direction == "an" or direction == "en" then
--- entry.level = level + 2
--- end
--- end
--- end
--- -- I2
--- for i=start,limit do
--- local entry = list[i]
--- local level = entry.level
--- if level % 2 == 1 then -- odd(level)
--- local direction = entry.direction
--- if direction == "l" or direction == "en" or direction == "an" then
--- entry.level = level + 1
--- end
--- end
--- end
--- end
-
local function resolve_implicit(list,size,start,limit,orderbefore,orderafter,baselevel)
for i=start,limit do
local entry = list[i]
@@ -852,60 +833,6 @@ local function resolve_levels(list,size,baselevel,analyze_fences)
end
end
--- local function insert_dir_points(list,size)
--- -- L2, but no actual reversion is done, we simply annotate where
--- -- begindir/endddir node will be inserted.
--- local maxlevel = 0
--- local finaldir = false
--- local toggle = true
--- for i=1,size do
--- local level = list[i].level
--- if level > maxlevel then
--- maxlevel = level
--- end
--- end
--- for level=0,maxlevel do
--- local started -- = false
--- local begindir -- = nil
--- local enddir -- = nil
--- local prev -- = nil
--- if toggle then
--- begindir = "+TLT"
--- enddir = "-TLT"
--- toggle = false
--- else
--- begindir = "+TRT"
--- enddir = "-TRT"
--- toggle = true
--- end
--- for i=1,size do
--- local entry = list[i]
--- if entry.level >= level then
--- if not started then
--- entry.begindir = begindir
--- started = true
--- end
--- else
--- if started then
--- prev.enddir = enddir
--- started = false
--- end
--- end
--- prev = entry
--- end
--- -- make sure to close the run at end of line
--- if started then
--- finaldir = enddir
--- end
--- end
--- if finaldir then
--- list[size].enddir = finaldir
--- end
--- for i=1,size do
--- print("<",i,list[i].level,list[i].begindir,list[i].enddir)
--- end
--- end
-
local stack = { }
local function insert_dir_points(list,size)
@@ -925,12 +852,12 @@ local function insert_dir_points(list,size)
local enddir -- = nil
local prev -- = nil
if toggle then
- begindir = "+TLT"
- enddir = "-TLT"
+ begindir = lefttoright_code
+ enddir = lefttoright_code
toggle = false
else
- begindir = "+TRT"
- enddir = "-TRT"
+ begindir = righttoleft_code
+ enddir = righttoleft_code
toggle = true
end
for i=1,size do
@@ -969,15 +896,18 @@ local function insert_dir_points(list,size)
if trace_list and n > 1 then
report_directions("unbalanced list")
end
- last.enddir = stack[n] == "+TRT" and "-TRT" or "-TLT"
+ last.enddir = stack[n]
end
end
end
+-- We flag nodes that can be skipped when we see them again but because whatever
+-- mechanism can injetc dir nodes that then are not flagged, we don't flag dir
+-- nodes that we inject here.
+
local function apply_to_list(list,size,head,pardir)
local index = 1
local current = head
- local done = false
if trace_list then
report_directions("start run")
end
@@ -990,7 +920,12 @@ local function apply_to_list(list,size,head,pardir)
local entry = list[index]
local begindir = entry.begindir
local enddir = entry.enddir
- local p = properties[current] if p then p.directions = true else properties[current] = { directions = true } end
+ local p = properties[current]
+ if p then
+ p.directions = true
+ else
+ properties[current] = { directions = true }
+ end
if id == glyph_code then
local mirror = entry.mirror
if mirror then
@@ -1011,55 +946,43 @@ local function apply_to_list(list,size,head,pardir)
setcolor(current,direction,false,mirror)
end
elseif id == hlist_code or id == vlist_code then
- setdir(current,pardir) -- is this really needed?
+ setdirection(current,pardir) -- is this really needed?
elseif id == glue_code then
if enddir and getsubtype(current) == parfillskip_code then
-- insert the last enddir before \parfillskip glue
- local d = new_textdir(enddir)
- local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end
- -- setattrlist(d,current)
- head = insert_node_before(head,current,d)
+ head = insert_node_before(head,current,new_direction(enddir,true))
enddir = false
- done = true
end
elseif begindir then
- if id == localpar_code then
+ if id == localpar_code and getsubtype(current) == 0 then
-- localpar should always be the 1st node
- local d = new_textdir(begindir)
- local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end
- -- setattrlist(d,current)
- head, current = insert_node_after(head,current,d)
+ head, current = insert_node_after(head,current,new_direction(begindir))
begindir = nil
- done = true
end
end
if begindir then
- local d = new_textdir(begindir)
- local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end
- -- setattrlist(d,current)
- head = insert_node_before(head,current,d)
- done = true
+ head = insert_node_before(head,current,new_direction(begindir))
end
local skip = entry.skip
if skip and skip > 0 then
for i=1,skip do
current = getnext(current)
- local p = properties[current] if p then p.directions = true else properties[current] = { directions = true } end
+ local p = properties[current]
+ if p then
+ p.directions = true
+ else
+ properties[current] = { directions = true }
+ end
end
end
if enddir then
- local d = new_textdir(enddir)
- local p = properties[d] if p then p.directions = true else properties[d] = { directions = true } end
- -- setattrlist(d,current)
- head, current = insert_node_after(head,current,d)
- done = true
+ head, current = insert_node_after(head,current,new_direction(enddir,true))
end
if not entry.remove then
current = getnext(current)
elseif remove_controls then
-- X9
head, current = remove_node(head,current,true)
- done = true
else
current = getnext(current)
end
@@ -1068,7 +991,7 @@ local function apply_to_list(list,size,head,pardir)
if trace_list then
report_directions("stop run")
end
- return head, done
+ return head
end
-- If needed we can optimize for only_one. There is no need to do anything
@@ -1077,16 +1000,15 @@ end
-- have more than one node. Actually, we only enter this function when we
-- do have a glyph!
-local function process(head,direction,only_one)
- head = tonut(head)
+local function process(head,direction,only_one,where)
-- for the moment a whole paragraph property
local attr = getattr(head,a_directions)
local analyze_fences = getfences(attr)
--
- local list, size = build_list(head)
- local baselevel, pardir, dirfound = get_baselevel(head,list,size,direction) -- we always have an inline dir node in context
+ local list, size = build_list(head,where)
+ local baselevel, dirfound = get_baselevel(head,list,size,direction)
if trace_details then
- report_directions("analyze: direction %a, baselevel %a",dirfound and pardir or "unknown",baselevel or 1)
+ report_directions("analyze: baselevel %a",baselevel == righttoleft_code and "r2l" or "l2r")
report_directions("before : %s",show_list(list,size,"original"))
end
resolve_explicit(list,size,baselevel)
@@ -1096,8 +1018,12 @@ local function process(head,direction,only_one)
report_directions("after : %s",show_list(list,size,"direction"))
report_directions("result : %s",show_done(list,size))
end
- local head, done = apply_to_list(list,size,head,pardir)
- return tonode(head), done
+ return apply_to_list(list,size,head,baselevel)
end
-directions.installhandler(interfaces.variables.three,process)
+local variables = interfaces.variables
+
+directions.installhandler(variables.one, process) -- for old times sake
+directions.installhandler(variables.two, process) -- for old times sake
+directions.installhandler(variables.three, process) -- for old times sake
+directions.installhandler(variables.unicode,process)
diff --git a/tex/context/base/mkiv/typo-fkr.lua b/tex/context/base/mkiv/typo-fkr.lua
index a1135d0f3..1fd08526c 100644
--- a/tex/context/base/mkiv/typo-fkr.lua
+++ b/tex/context/base/mkiv/typo-fkr.lua
@@ -7,12 +7,10 @@ if not modules then modules = { } end modules ['typo-fkr'] = {
}
local nuts = nodes.nuts
-local tonut = nuts.tonut
local getid = nuts.getid
local getnext = nuts.getnext
-local getchar = nuts.getchar
-local getfont = nuts.getfont
local getattr = nuts.getattr
+local isglyph = nuts.isglyph
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
@@ -32,20 +30,15 @@ local a_extrakern = attributes.private("extrafontkern")
typesetters.fontkerns = { }
function typesetters.fontkerns.handler(head)
- local kepthead = head
- local head = tonut(head)
local current = head
local lastfont = nil
local lastchar = nil
local lastdata = nil
- local done = false
while current do
- local id = getid(current)
- if id == glyph_code then
+ local char, font = isglyph(current)
+ if char then
local a = getattr(current,a_extrakern)
if a then
- local char = getchar(current)
- local font = getfont(current)
if font ~= lastfont then
if a > 0 and lastchar then
if not lastdata then
@@ -64,7 +57,6 @@ function typesetters.fontkerns.handler(head)
end
if kern ~= 0 then
head, current = insert_before(head,current,new_kern(kern))
- done = true
end
lastdata = data
else
@@ -77,7 +69,6 @@ function typesetters.fontkerns.handler(head)
local kern = getkernpair(lastdata,lastchar,char)
if kern ~= 0 then
head, current = insert_before(head,current,new_kern(kern))
- done = true
end
end
lastchar = char
@@ -94,7 +85,7 @@ function typesetters.fontkerns.handler(head)
end
current = getnext(current)
end
- return kepthead, done
+ return head
end
if context then
diff --git a/tex/context/base/mkiv/typo-fln.lua b/tex/context/base/mkiv/typo-fln.lua
index 4fb82ce44..048980732 100644
--- a/tex/context/base/mkiv/typo-fln.lua
+++ b/tex/context/base/mkiv/typo-fln.lua
@@ -30,7 +30,6 @@ local context = context
local implement = interfaces.implement
local nuts = nodes.nuts
-local tonut = nuts.tonut
local tonode = nuts.tonode
local getnext = nuts.getnext
@@ -38,7 +37,6 @@ local getprev = nuts.getprev
local getboth = nuts.getboth
local setboth = nuts.setboth
local getid = nuts.getid
-local getsubtype = nuts.getsubtype
local getwidth = nuts.getwidth
local getlist = nuts.getlist
local setlist = nuts.setlist
@@ -58,14 +56,16 @@ local glue_code = nodecodes.glue
local spaceskip_code = nodes.gluecodes.spaceskip
-local traverse_id = nuts.traverse_id
+local nextglyph = nuts.traversers.glyph
+local nextdisc = nuts.traversers.disc
+
local flush_node_list = nuts.flush_list
local flush_node = nuts.flush_node
local copy_node_list = nuts.copy_list
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
local remove_node = nuts.remove
-local list_dimensions = nuts.dimensions
+local getdimensions = nuts.dimensions
local hpack_node_list = nuts.hpack
local nodepool = nuts.pool
@@ -136,7 +136,7 @@ actions[v_line] = function(head,setting)
local linebreaks = { }
local function set(head)
- for g in traverse_id(glyph_code,head) do
+ for g in nextglyph, head do
if dynamic > 0 then
setattr(g,0,dynamic)
end
@@ -146,7 +146,7 @@ actions[v_line] = function(head,setting)
set(temp)
- for g in traverse_id(disc_code,temp) do
+ for g in nextdisc, temp do
local pre, post, replace = getdisc(g)
if pre then
set(pre)
@@ -173,17 +173,13 @@ actions[v_line] = function(head,setting)
local function list_dimensions(list,start)
local temp = copy_node_list(list,start)
- temp = tonode(temp)
temp = nodes.handlers.characters(temp)
temp = nodes.injections.handler(temp)
-- temp = typesetters.fontkerns.handler(temp) -- maybe when enabled
- -- nodes.handlers.protectglyphs(temp) -- not needed as we discard
+ -- nodes.handlers.protectglyphs(temp) -- not needed as we discard
-- temp = typesetters.spacings.handler(temp) -- maybe when enabled
-- temp = typesetters.kerns.handler(temp) -- maybe when enabled
- temp = tonut(temp)
- temp = hpack_node_list(temp)
- local width = getwidth(temp)
- flush_node_list(temp)
+ local width = getdimensions(temp)
return width
end
@@ -206,7 +202,7 @@ actions[v_line] = function(head,setting)
while start do
local id = getid(start)
if id == glyph_code then
- n = n + 1
+ -- go on
elseif id == disc_code then
-- this could be an option
n = n + 1
@@ -218,7 +214,8 @@ actions[v_line] = function(head,setting)
end
elseif id == kern_code then -- todo: fontkern
-- this could be an option
- elseif n > 0 then
+ elseif id == glue_code then
+ n = n + 1
if try() then
break
end
@@ -255,7 +252,6 @@ actions[v_line] = function(head,setting)
local id = getid(start)
local ok = false
if id == glyph_code then
- n = n + 1
update(start)
elseif id == disc_code then
n = n + 1
@@ -264,7 +260,7 @@ actions[v_line] = function(head,setting)
if linebreak == n then
local p, n = getboth(start)
if pre then
- for current in traverse_id(glyph_code,pre) do
+ for current in nextglyph, pre do
update(current)
end
setlink(pretail,n)
@@ -284,7 +280,7 @@ actions[v_line] = function(head,setting)
else
local p, n = getboth(start)
if replace then
- for current in traverse_id(glyph_code,replace) do
+ for current in nextglyph, replace do
update(current)
end
setlink(replacetail,n)
@@ -299,22 +295,30 @@ actions[v_line] = function(head,setting)
setdisc(disc,pre,post,replace)
flush_node(disc)
elseif id == glue_code then
- head = insert_node_before(head,start,newpenalty(10000)) -- nobreak
+ n = n + 1
+ if linebreak ~= n then
+ head = insert_node_before(head,start,newpenalty(10000)) -- nobreak
+ end
end
+ local next = getnext(start)
if linebreak == n then
- if trace_firstlines then
- head, start = insert_node_after(head,start,newpenalty(10000)) -- nobreak
- head, start = insert_node_after(head,start,newkern(-65536))
- head, start = insert_node_after(head,start,tracerrule(65536,4*65536,2*65536,"darkblue"))
+ if start ~= head then
+ local where = id == glue_code and getprev(start) or start
+ if trace_firstlines then
+ head, where = insert_node_after(head,where,newpenalty(10000)) -- nobreak
+ head, where = insert_node_after(head,where,newkern(-65536))
+ head, where = insert_node_after(head,where,tracerrule(65536,4*65536,2*65536,"darkblue"))
+ end
+ head, where = insert_node_after(head,where,newpenalty(-10000)) -- break
end
- head, start = insert_node_after(head,start,newpenalty(-10000)) -- break
+ start = next
break
end
- start = getnext(start)
+ start = next
end
end
- return head, true
+ return head
end
actions[v_word] = function(head,setting)
@@ -359,13 +363,12 @@ actions[v_word] = function(head,setting)
end
start = getnext(start)
end
- return head, true
+ return head
end
actions[v_default] = actions[v_line]
function firstlines.handler(head)
- head = tonut(head)
local start = head
local attr = nil
while start do
@@ -388,11 +391,10 @@ function firstlines.handler(head)
if trace_firstlines then
report_firstlines("processing firstlines, alternative %a",alternative)
end
- local head, done = action(head,settings)
- return tonode(head), done
+ return action(head,settings)
end
end
- return tonode(head), false
+ return head
end
-- goodie
@@ -401,7 +403,7 @@ local function applytofirstcharacter(box,what)
local tbox = getbox(box) -- assumes hlist
local list = getlist(tbox)
local done = nil
- for n in traverse_id(glyph_code,list) do
+ for n in nextglyph, list do
list = remove_node(list,n)
done = n
break
diff --git a/tex/context/base/mkiv/typo-fln.mkiv b/tex/context/base/mkiv/typo-fln.mkiv
index 37348be29..533c197cd 100644
--- a/tex/context/base/mkiv/typo-fln.mkiv
+++ b/tex/context/base/mkiv/typo-fln.mkiv
@@ -91,7 +91,7 @@
\kern\zeropoint % we need a node
% \hskip\zeropoint\s!plus\emwidth\relax % can be an option
\endgroup
- \globallet\typo_firstline_handle\relax}
+ \glet\typo_firstline_handle\relax}
\let\typo_firstline_handle\relax
diff --git a/tex/context/base/mkiv/typo-itc.lua b/tex/context/base/mkiv/typo-itc.lua
index 328bf1406..2683eecc3 100644
--- a/tex/context/base/mkiv/typo-itc.lua
+++ b/tex/context/base/mkiv/typo-itc.lua
@@ -29,13 +29,9 @@ local enableaction = nodes.tasks.enableaction
local nuts = nodes.nuts
local nodepool = nuts.pool
-local tonode = nuts.tonode
-local tonut = nuts.tonut
-
local getprev = nuts.getprev
local getnext = nuts.getnext
local getid = nuts.getid
-local getfont = nuts.getfont
local getchar = nuts.getchar
local getdisc = nuts.getdisc
local getattr = nuts.getattr
@@ -128,14 +124,22 @@ local function okay(data,current,font,prevchar,previtalic,char,what)
return false
end
if threshold then
- local ht = getheight(current)
- local ex = exheights[font]
- local th = threshold * ex
- if ht <= th then
- if trace_italics then
- report_italics("ignoring correction between %s italic %C and regular %C, height %p less than threshold %p",prevchar,what,char,ht,th)
+ -- if getid(current) == glyph_code then
+ while current and getid(current) ~= glyph_code do
+ current = getprev(current)
+ end
+ if current then
+ local ht = getheight(current)
+ local ex = exheights[font]
+ local th = threshold * ex
+ if ht <= th then
+ if trace_italics then
+ report_italics("ignoring correction between %s italic %C and regular %C, height %p less than threshold %p",prevchar,what,char,ht,th)
+ end
+ return false
end
- return false
+ else
+ -- maybe backtrack to glyph
end
end
if trace_italics then
@@ -177,7 +181,7 @@ local textokay = false
local enablemath = false
local enabletext = false
-local function domath(head,current, done)
+local function domath(head,current)
current = end_of_math(current)
local next = getnext(current)
if next then
@@ -200,8 +204,7 @@ local function domath(head,current, done)
a = a + 100
end
local i = getkern(kern)
- local f = getfont(glyph)
- local c = getchar(glyph)
+ local c, f = isglyph(glyph)
if getheight(next) < 1.25*exheights[f] then
if i == 0 then
if trace_italics then
@@ -212,7 +215,6 @@ local function domath(head,current, done)
report_italics("%s italic between math %C and punctuation %C","removing",i,c,char)
end
setkern(kern,0) -- or maybe a small value or half the ic
- done = true
end
elseif i == 0 then
local d = chardata[f][c]
@@ -226,7 +228,6 @@ local function domath(head,current, done)
if trace_italics then
report_italics("%s italic %p between math %C and punctuation %C","setting",i,c,char)
end
- done = true
end
elseif trace_italics then
report_italics("%s italic %p between math %C and punctuation %C","keeping",k,c,char)
@@ -251,34 +252,31 @@ local function domath(head,current, done)
report_italics("%s italic %p between math %C and non punctuation %C","adding",a,getchar(glyph),char)
end
insert_node_after(head,glyph,correction_kern(a,glyph))
- done = true
end
end
end
end
end
end
- return current, done
+ return current
end
local function mathhandler(head)
- local nuthead = tonut(head)
- local current = nuthead
- local done = false
+ local current = head
while current do
if getid(current) == math_code then
- current, done = domath(nuthead,current,done)
+ current = domath(head,current)
end
current = getnext(current)
end
- return head, done
+ return head
end
local function texthandler(head)
local prev = nil
local prevchar = nil
- local prevhead = tonut(head)
+ local prevhead = head
local previtalic = 0
local previnserted = nil
@@ -300,20 +298,18 @@ local function texthandler(head)
local replaceinserted = nil
local current = prevhead
- local done = false
local lastfont = nil
local lastattr = nil
while current do
local char, id = isglyph(current)
if char then
- local font = getfont(current)
+ local font = id
local data = italicsdata[font]
if font ~= lastfont then
if previtalic ~= 0 then
if okay(data,current,font,prevchar,previtalic,char,"glyph") then
insert_node_after(prevhead,prev,correction_kern(previtalic,current))
- done = true
end
elseif previnserted and data then
if trace_italics then
@@ -325,7 +321,6 @@ local function texthandler(head)
if replaceitalic ~= 0 then
if okay(data,replace,font,replacechar,replaceitalic,char,"replace") then
insert_node_after(replacehead,replace,correction_kern(replaceitalic,current))
- done = true
end
replaceitalic = 0
elseif replaceinserted and data then
@@ -338,7 +333,6 @@ local function texthandler(head)
if postitalic ~= 0 then
if okay(data,post,font,postchar,postitalic,char,"post") then
insert_node_after(posthead,post,correction_kern(postitalic,current))
- done = true
end
postitalic = 0
elseif postinserted and data then
@@ -395,7 +389,7 @@ local function texthandler(head)
while current do
local char, id = isglyph(current)
if char then
- local font = getfont(current)
+ local font = id
local data = italicsdata[font]
if data then
local attr = forcedvariant or getattr(current,a_italics)
@@ -431,7 +425,7 @@ local function texthandler(head)
while current do
local char, id = isglyph(current)
if char then
- local font = getfont(current)
+ local font = id
local data = italicsdata[font]
if data then
local attr = forcedvariant or getattr(current,a_italics)
@@ -479,7 +473,6 @@ local function texthandler(head)
end
previnserted = correction_glue(previtalic,current) -- maybe just add ? else problem with penalties
previtalic = 0
- done = true
insert_node_after(prevhead,prev,previnserted)
else
if replaceitalic ~= 0 then
@@ -488,7 +481,6 @@ local function texthandler(head)
end
replaceinserted = correction_kern(replaceitalic,current) -- needs to be a kern
replaceitalic = 0
- done = true
insert_node_after(replacehead,replace,replaceinserted)
end
if postitalic ~= 0 then
@@ -497,7 +489,6 @@ local function texthandler(head)
end
postinserted = correction_kern(postitalic,current) -- needs to be a kern
postitalic = 0
- done = true
insert_node_after(posthead,post,postinserted)
end
end
@@ -510,7 +501,7 @@ local function texthandler(head)
postinserted = nil
postitalic = 0
if mathokay then
- current, done = domath(head,current,done)
+ current = domath(head,current)
else
current = end_of_math(current)
end
@@ -526,7 +517,6 @@ local function texthandler(head)
replaceitalic = 0
postinserted = nil
postitalic = 0
- done = true
else
if replaceitalic ~= 0 then
if trace_italics then
@@ -539,7 +529,6 @@ local function texthandler(head)
replaceitalic = 0
postinserted = nil
postitalic = 0
- done = true
end
if postitalic ~= 0 then
if trace_italics then
@@ -552,7 +541,6 @@ local function texthandler(head)
replaceitalic = 0
postinserted = nil
postitalic = 0
- done = true
end
end
end
@@ -564,25 +552,22 @@ local function texthandler(head)
report_italics("inserting %p between %s italic %C and end of list",previtalic,"glyph",prevchar)
end
insert_node_after(prevhead,prev,correction_kern(previtalic,current))
- done = true
else
if replaceitalic ~= 0 then
if trace_italics then
report_italics("inserting %p between %s italic %C and end of list",replaceitalic,"replace",replacechar)
end
insert_node_after(replacehead,replace,correction_kern(replaceitalic,current))
- done = true
end
if postitalic ~= 0 then
if trace_italics then
report_italics("inserting %p between %s italic %C and end of list",postitalic,"post",postchar)
end
insert_node_after(posthead,post,correction_kern(postitalic,current))
- done = true
end
end
end
- return head, done
+ return head
end
function italics.handler(head)
diff --git a/tex/context/base/mkiv/typo-krn.lua b/tex/context/base/mkiv/typo-krn.lua
index 71d9736a4..c26004a49 100644
--- a/tex/context/base/mkiv/typo-krn.lua
+++ b/tex/context/base/mkiv/typo-krn.lua
@@ -21,9 +21,6 @@ local enableaction = nodes.tasks.enableaction
local nuts = nodes.nuts
local nodepool = nuts.pool
-local tonode = nuts.tonode
-local tonut = nuts.tonut
-
-- check what is used
local find_node_tail = nuts.tail
@@ -32,6 +29,7 @@ local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
local end_of_math = nuts.end_of_math
local use_components = nuts.use_components
+local copy_node = nuts.copy
local getnext = nuts.getnext
local getprev = nuts.getprev
@@ -43,10 +41,12 @@ local getdisc = nuts.getdisc
local getglue = nuts.getglue
local getkern = nuts.getkern
local isglyph = nuts.isglyph
+local setchar = nuts.setchar
local setfield = nuts.setfield
local getattr = nuts.getattr
local takeattr = nuts.takeattr
+local setattr = nuts.setattr
local setlink = nuts.setlink
local setdisc = nuts.setdisc
local setglue = nuts.setglue
@@ -62,7 +62,7 @@ local new_glue = nodepool.glue
local nodecodes = nodes.nodecodes
local kerncodes = nodes.kerncodes
-local skipcodes = nodes.skipcodes
+local gluecodes = nodes.gluecodes
local disccodes = nodes.disccodes
local listcodes = nodes.listcodes
@@ -74,17 +74,18 @@ local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local math_code = nodecodes.math
-local box_list_code = listcodes.box
-local user_list_code = listcodes.unknown
+local boxlist_code = listcodes.box
+local unknownlist_code = listcodes.unknown
-local discretionary_code = disccodes.discretionary
-local automatic_code = disccodes.automatic
+local discretionarydisc_code = disccodes.discretionary
+local automaticdisc_code = disccodes.automatic
local fontkern_code = kerncodes.fontkern
local userkern_code = kerncodes.userkern
-local userskip_code = skipcodes.userskip
-local spaceskip_code = skipcodes.spaceskip
-local xspaceskip_code = skipcodes.xspaceskip
+
+local userskip_code = gluecodes.userskip
+local spaceskip_code = gluecodes.spaceskip
+local xspaceskip_code = gluecodes.xspaceskip
local fonthashes = fonts.hashes
local chardata = fonthashes.characters
@@ -132,9 +133,6 @@ local factors = kerns.factors
local gluefactor = 4 -- assumes quad = .5 enspace
-kerns.keepligature = false -- just for fun (todo: control setting with key/value)
-kerns.keeptogether = false -- just for fun (todo: control setting with key/value)
-
-- red : kept by dynamic feature
-- green : kept by static feature
-- blue : keep by goodie
@@ -257,7 +255,7 @@ end
local function inject_end(boundary,next,keeptogether,krn,ok)
local tail = find_node_tail(boundary)
- local char, id = getid(tail)
+ local char, id = isglyph(tail)
if id == kern_code then
if getsubtype(tail) == fontkern_code then
local inject = true
@@ -301,7 +299,7 @@ local function process_list(head,keeptogether,krn,font,okay)
local char, id = isglyph(start)
if char then
if not font then
- font = getfont(start)
+ font = id -- getfont(start)
mark = markdata[font]
kern = quaddata[font]*krn
end
@@ -354,19 +352,223 @@ local function closest_bound(b,get)
while b do
if not getattr(b,a_kerns) then
break
- elseif getid(b) == glyph_code then
- return b, getfont(b)
else
- b = get(b)
+ local c, f = isglyph(b)
+ if c then
+ return b, f
+ else
+ b = get(b)
+ end
end
end
end
end
+-- function kerns.handler(head)
+-- local start = head
+-- local lastfont = nil
+-- local keepligature = kerns.keepligature
+-- local keeptogether = kerns.keeptogether
+-- local fillup = false
+-- local bound = false
+-- local prev = nil
+-- local previd = nil
+-- local prevchar = nil
+-- local prevfont = nil
+-- local prevmark = nil
+-- while start do
+-- -- fontkerns don't get the attribute but they always sit between glyphs so
+-- -- are always valid bound .. disc nodes also somtimes don't get them
+-- local id = getid(start)
+-- local attr = takeattr(start,a_kerns)
+-- if attr and attr > 0 then
+-- local krn = mapping[attr]
+-- if krn == v_max then
+-- krn = .25
+-- fillup = true
+-- else
+-- fillup = false
+-- end
+-- if not krn or krn == 0 then
+-- bound = false
+-- elseif id == glyph_code then
+-- if keepligature and keepligature(start) then
+-- -- keep 'm
+-- else
+-- -- we could use the subtype ligature but that's also a call
+-- -- todo: check tounicode and use that information to split
+-- head, start = use_components(head,start)
+-- end
+-- local char, font = isglyph(start)
+-- local mark = markdata[font]
+-- if not bound then
+-- -- yet
+-- elseif mark[char] then
+-- -- skip
+-- elseif previd == kern_code then
+-- if getsubtype(prev) == fontkern_code then
+-- local inject = true
+-- if keeptogether then
+-- if previd == glyph_code and keeptogether(prev,start) then
+-- inject = false
+-- end
+-- end
+-- if inject then
+-- -- not yet ok, as injected kerns can be overlays (from node-inj.lua)
+-- setkern(prev,getkern(prev) + quaddata[font]*krn,userkern_code)
+-- end
+-- end
+-- elseif previd == glyph_code then
+-- if prevfont == font then
+-- if keeptogether and keeptogether(prev,start) then
+-- -- keep 'm
+-- else
+-- local data = chardata[font][prevchar]
+-- local kerns = data and data.kerns
+-- local kern = (kerns and kerns[char] or 0) + quaddata[font]*krn
+-- insert_node_before(head,start,kern_injector(fillup,kern))
+-- end
+-- else
+-- insert_node_before(head,start,kern_injector(fillup,quaddata[font]*krn))
+-- end
+-- end
+-- prev = start
+-- prevchar = char
+-- prevfont = font
+-- prevmark = mark
+-- previd = id
+-- bound = true
+-- elseif id == disc_code then
+-- local prev, next, pglyph, nglyph -- delayed till needed
+-- local subtype = getsubtype(start)
+-- -- if subtype == automaticdisc_code then
+-- -- -- this is kind of special, as we have already injected the
+-- -- -- previous kern
+-- -- local prev = getprev(start)
+-- -- local pglyph = prev and getid(prev) == glyph_code
+-- -- languages.expand(start,pglyph and prev)
+-- -- -- we can have a different start now
+-- -- elseif subtype ~= discretionarydisc_code then
+-- -- prev = getprev(start)
+-- -- pglyph = prev and getid(prev) == glyph_code
+-- -- languages.expand(start,pglyph and prev)
+-- -- end
+-- local pre, post, replace = getdisc(start)
+-- local indeed = false
+-- if pre then
+-- local okay = false
+-- if not prev then
+-- prev = getprev(start)
+-- pglyph = prev and getid(prev) == glyph_code
+-- end
+-- if pglyph then
+-- pre, okay = inject_begin(pre,prev,keeptogether,krn,okay)
+-- end
+-- pre, okay = process_list(pre,keeptogether,krn,false,okay)
+-- if okay then
+-- indeed = true
+-- end
+-- end
+-- if post then
+-- local okay = false
+-- if not next then
+-- next = getnext(start)
+-- nglyph = next and getid(next) == glyph_code
+-- end
+-- if nglyph then
+-- post, okay = inject_end(post,next,keeptogether,krn,okay)
+-- end
+-- post, okay = process_list(post,keeptogether,krn,false,okay)
+-- if okay then
+-- indeed = true
+-- end
+-- end
+-- if replace then
+-- local okay = false
+-- if not prev then
+-- prev = getprev(start)
+-- pglyph = prev and getid(prev) == glyph_code
+-- end
+-- if pglyph then
+-- replace, okay = inject_begin(replace,prev,keeptogether,krn,okay)
+-- end
+-- if not next then
+-- next = getnext(start)
+-- nglyph = next and getid(next) == glyph_code
+-- end
+-- if nglyph then
+-- replace, okay = inject_end(replace,next,keeptogether,krn,okay)
+-- end
+-- replace, okay = process_list(replace,keeptogether,krn,false,okay)
+-- if okay then
+-- indeed = true
+-- end
+-- elseif prevfont then
+-- replace = new_kern(quaddata[prevfont]*krn)
+-- indeed = true
+-- end
+-- if indeed then
+-- setdisc(start,pre,post,replace)
+-- end
+-- bound = false
+-- elseif id == kern_code then
+-- bound = getsubtype(start) == fontkern_code
+-- prev = start
+-- previd = id
+-- elseif id == glue_code then
+-- local subtype = getsubtype(start)
+-- if subtype == userskip_code or subtype == xspaceskip_code or subtype == spaceskip_code then
+-- local width, stretch, shrink, stretch_order, shrink_order = getglue(start)
+-- if width > 0 then
+-- local w = width + gluefactor * width * krn
+-- stretch = stretch * w / width
+-- shrink = shrink * w / width
+-- if fillup then
+-- stretch = 2 * stretch
+-- shrink = 2 * shrink
+-- stretch_order = 1
+-- -- shrink_order = 1 ?
+-- end
+-- setglue(start,w,stretch,shrink,stretch_order,shrink_order)
+-- end
+-- end
+-- bound = false
+-- elseif id == hlist_code or id == vlist_code then
+-- local subtype = getsubtype(start)
+-- if subtype == unknownlist_code or subtype == boxlist_code then
+-- -- special case
+-- local b, f = closest_bound(start,getprev)
+-- if b then
+-- insert_node_before(head,start,kern_injector(fillup,quaddata[f]*krn))
+-- end
+-- local b, f = closest_bound(start,getnext)
+-- if b then
+-- insert_node_after(head,start,kern_injector(fillup,quaddata[f]*krn))
+-- end
+-- end
+-- bound = false
+-- elseif id == math_code then
+-- start = end_of_math(start)
+-- bound = false
+-- end
+-- if start then
+-- start = getnext(start)
+-- end
+-- elseif id == kern_code then
+-- bound = getsubtype(start) == fontkern_code
+-- prev = start
+-- previd = id
+-- start = getnext(start)
+-- else
+-- bound = false
+-- start = getnext(start)
+-- end
+-- end
+-- return head
+-- end
+
function kerns.handler(head)
- local head = tonut(head)
local start = head
- local done = false
local lastfont = nil
local keepligature = kerns.keepligature
local keeptogether = kerns.keeptogether
@@ -379,10 +581,10 @@ function kerns.handler(head)
local prevmark = nil
while start do
-- fontkerns don't get the attribute but they always sit between glyphs so
- -- are always valid bound .. disc nodes also somtimes don't get them
- local id = getid(start)
+ -- are always valid bound .. disc nodes also sometimes don't get them
local attr = takeattr(start,a_kerns)
if attr and attr > 0 then
+ local char, id = isglyph(start)
local krn = mapping[attr]
if krn == v_max then
krn = .25
@@ -392,17 +594,34 @@ function kerns.handler(head)
end
if not krn or krn == 0 then
bound = false
- elseif id == glyph_code then
+ elseif char then -- id == glyph_code
+ local font = id -- more readable
+ local mark = markdata[font]
if keepligature and keepligature(start) then
-- keep 'm
else
- -- we could use the subtype ligature but that's also a call
- -- todo: check tounicode and use that information to split
- head, start = use_components(head,start)
+ -- head, start = use_components(head,start)
+ -- beware, these are not kerned so we mighty need a kern only pass
+ -- maybe some day .. anyway, one should disable ligaturing
+ local data = chardata[font][char]
+ if data then
+ local unicode = data.unicode -- can be cached
+ if type(unicode) == "table" then
+ char = unicode[1]
+ local s = start
+ setchar(s,char)
+ for i=2,#unicode do
+ local n = copy_node(s)
+ if i == 2 then
+ setattr(n,a_kerns,attr) -- we took away the attr
+ end
+ setchar(n,unicode[i])
+ insert_node_after(head,s,n)
+ s = n
+ end
+ end
+ end
end
- local char = getchar(start)
- local font = getfont(start)
- local mark = markdata[font]
if not bound then
-- yet
elseif mark[char] then
@@ -418,7 +637,6 @@ function kerns.handler(head)
if inject then
-- not yet ok, as injected kerns can be overlays (from node-inj.lua)
setkern(prev,getkern(prev) + quaddata[font]*krn,userkern_code)
- done = true
end
end
elseif previd == glyph_code then
@@ -426,34 +644,33 @@ function kerns.handler(head)
if keeptogether and keeptogether(prev,start) then
-- keep 'm
else
+ -- hm, only basemode ... will go away ...
local data = chardata[font][prevchar]
local kerns = data and data.kerns
local kern = (kerns and kerns[char] or 0) + quaddata[font]*krn
insert_node_before(head,start,kern_injector(fillup,kern))
- done = true
end
else
insert_node_before(head,start,kern_injector(fillup,quaddata[font]*krn))
- done = true
end
end
prev = start
prevchar = char
prevfont = font
prevmark = mark
- previd = id
+ previd = glyph_code -- id
bound = true
elseif id == disc_code then
local prev, next, pglyph, nglyph -- delayed till needed
local subtype = getsubtype(start)
- -- if subtype == automatic_code then
+ -- if subtype == automaticdisc_code then
-- -- this is kind of special, as we have already injected the
-- -- previous kern
-- local prev = getprev(start)
-- local pglyph = prev and getid(prev) == glyph_code
-- languages.expand(start,pglyph and prev)
-- -- we can have a different start now
- -- elseif subtype ~= discretionary_code then
+ -- elseif subtype ~= discretionarydisc_code then
-- prev = getprev(start)
-- pglyph = prev and getid(prev) == glyph_code
-- languages.expand(start,pglyph and prev)
@@ -514,7 +731,6 @@ function kerns.handler(head)
end
if indeed then
setdisc(start,pre,post,replace)
- done = true
end
bound = false
elseif id == kern_code then
@@ -536,23 +752,20 @@ function kerns.handler(head)
-- shrink_order = 1 ?
end
setglue(start,w,stretch,shrink,stretch_order,shrink_order)
- done = true
end
end
bound = false
elseif id == hlist_code or id == vlist_code then
local subtype = getsubtype(start)
- if subtype == user_list_code or subtype == box_list_code then
+ if subtype == unknownlist_code or subtype == boxlist_code then
-- special case
local b, f = closest_bound(start,getprev)
if b then
insert_node_before(head,start,kern_injector(fillup,quaddata[f]*krn))
- done = true
end
local b, f = closest_bound(start,getnext)
if b then
insert_node_after(head,start,kern_injector(fillup,quaddata[f]*krn))
- done = true
end
end
bound = false
@@ -563,17 +776,20 @@ function kerns.handler(head)
if start then
start = getnext(start)
end
- elseif id == kern_code then
- bound = getsubtype(start) == fontkern_code
- prev = start
- previd = id
- start = getnext(start)
else
- bound = false
- start = getnext(start)
+ local id = getid(start)
+ if id == kern_code then
+ bound = getsubtype(start) == fontkern_code
+ prev = start
+ previd = id
+ start = getnext(start)
+ else
+ bound = false
+ start = getnext(start)
+ end
end
end
- return tonode(head), done
+ return head
end
local enabled = false
diff --git a/tex/context/base/mkiv/typo-lin.lua b/tex/context/base/mkiv/typo-lin.lua
index ebf748a82..8393ea65b 100644
--- a/tex/context/base/mkiv/typo-lin.lua
+++ b/tex/context/base/mkiv/typo-lin.lua
@@ -64,7 +64,7 @@ local listcodes = nodes.listcodes
local hlist_code = nodecodes.hlist
local glue_code = nodecodes.glue
local kern_code = nodecodes.kern
-local line_code = listcodes.line
+local linelist_code = listcodes.line
----- localpar_code = nodecodes.localpar
local leftskip_code = gluecodes.leftskip
local rightskip_code = gluecodes.rightskip
@@ -73,7 +73,7 @@ local parfillskip_code = gluecodes.parfillskip
local tonut = nodes.tonut
local tonode = nodes.tonode
-local traverse_id = nuts.traverse_id
+local nexthlist = nuts.traversers.hlist
local insert_before = nuts.insert_before
local insert_after = nuts.insert_after
local find_tail = nuts.tail
@@ -90,7 +90,7 @@ local getboth = nuts.getboth
local setlink = nuts.setlink
local setkern = nuts.setkern
local getkern = nuts.getkern
-local getdir = nuts.getdir
+local getdirection = nuts.getdirection
local getshift = nuts.getshift
local setshift = nuts.setshift
local getwidth = nuts.getwidth
@@ -109,6 +109,8 @@ local new_hlist = nodepool.hlist
local new_rule = nodepool.rule
local new_glue = nodepool.glue
+local righttoleft_code = nodes.dirvalues.righttoleft
+
local texgetcount = tex.getcount
local texgetglue = tex.getglue
local setmetatableindex = table.setmetatableindex
@@ -127,22 +129,12 @@ local noflines = 0
-- This is the third version, a mix between immediate (prestice lines) and delayed
-- as we don't want anchors that are not used.
--- if reverse then delta = - delta end
--- head = insert_before(head,head,nodepool.textdir("-TLT"))
--- ....
--- head = insert_before(head,head,nodepool.textdir("TLT"))
-
--- todo: figure out metatable mess ... when we copy we also need to copy
--- anchors ... use rawgets
-
--- problem: what if a box is copied ... we could check an attribute
-
local function finalize(prop,key) -- delayed calculations
local line = prop.line
local hsize = prop.hsize
local width = prop.width
local shift = getshift(line) -- dangerous as it can be vertical as well
- local reverse = getdir(line) == "TRT" or false
+ local reverse = getdirection(line) == righttoleft_code or false
local pack = new_hlist()
local head = getlist(line)
local delta = 0
@@ -248,49 +240,47 @@ function paragraphs.normalize(head,islocal)
return head, false
end
-- this can become a separate handler but it makes sense to integrate it here
- local l_width, l_stretch, l_shrink = texgetglue("parfillleftskip")
- if l_width ~= 0 or l_stretch ~= 0 or l_shrink ~= 0 then
- local last = nil -- a nut
- local done = false
- for line in traverse_id(hlist_code,tonut(head)) do
- if getsubtype(line) == line_code and not getprop(line,"line") then
- if done then
- last = line
- else
- done = true
+ local mode = texgetcount("parfillleftmode")
+ if mode > 0 then
+ local l_width, l_stretch, l_shrink = texgetglue("parfillleftskip")
+ if l_width ~= 0 or l_stretch ~= 0 or l_shrink ~= 0 then
+ local last = nil -- a nut
+ local done = mode == 2 -- false
+ for line, subtype in nexthlist, head do
+ if subtype == linelist_code and not getprop(line,"line") then
+ if done then
+ last = line
+ else
+ done = true
+ end
end
end
- end
- if last then -- only if we have more than one line
- local head = getlist(last)
- local current = head
- if current then
- if getid(current) == glue_code and getsubtype(current,leftskip_code) then
- current = getnext(current)
- end
+ if last then -- only if we have more than one line
+ local head = getlist(last)
+ local current = head
if current then
- head, current = insert_before(head,current,new_glue(l_width,l_stretch,l_shrink))
- if head == current then
- setlist(last,head)
+ if getid(current) == glue_code and getsubtype(current,leftskip_code) then
+ current = getnext(current)
+ end
+ if current then
+ head, current = insert_before(head,current,new_glue(l_width,l_stretch,l_shrink))
+ if head == current then
+ setlist(last,head)
+ end
+ -- can be a 'rehpack(h )'
+ rehpack(last)
end
- -- can be a 'rehpack(h )'
- rehpack(last)
end
end
end
end
-- normalizer
- for line in traverse_id(hlist_code,tonut(head)) do
- if getsubtype(line) == line_code and not getprop(line,"line") then
+ for line, subtype in nexthlist, head do
+ if subtype == linelist_code and not getprop(line,"line") then
normalize(line)
- if done then
- last = line
- else
- done = true
- end
end
end
- return head, true
+ return head, true -- true is obsolete
end
-- print(nodes.idstostring(head))
@@ -418,12 +408,17 @@ function paragraphs.moveinline(n,blob,dx,dy)
end
end
-local lateluafunction = nodepool.lateluafunction
-local setposition = job.positions.set
-local t_anchor = { x = true, c = true }
+local latelua = nodepool.latelua
+local setposition = jobpositions.setspec
+local t_anchor = { x = true, c = true } -- needs checking
local function setanchor(h_anchor)
- return lateluafunction(function() setposition("md:h",h_anchor,t_anchor) end)
+ return latelua {
+ action = setposition,
+ name = "md:h",
+ index = h_anchor,
+ value = t_anchor, -- really shared ?
+ }
end
function paragraphs.calculatedelta(n,width,delta,atleft,islocal,followshape,area)
diff --git a/tex/context/base/mkiv/typo-mar.lua b/tex/context/base/mkiv/typo-mar.lua
index bc9c408c1..f8665e0b0 100644
--- a/tex/context/base/mkiv/typo-mar.lua
+++ b/tex/context/base/mkiv/typo-mar.lua
@@ -62,13 +62,11 @@ local nuts = nodes.nuts
local nodepool = nuts.pool
local tonode = nuts.tonode
-local tonut = nuts.tonut
local hpack_nodes = nuts.hpack
local traverse_id = nuts.traverse_id
local flush_node_list = nuts.flush_list
-local getfield = nuts.getfield
local getnext = nuts.getnext
local getprev = nuts.getprev
local getid = nuts.getid
@@ -84,6 +82,9 @@ local setshift = nuts.setshift
local getwidth = nuts.getwidth
local setwidth = nuts.setwidth
local getheight = nuts.getheight
+local getprop = nuts.getprop
+
+local setattrlist = nuts.setattrlist
local getbox = nuts.getbox
local takebox = nuts.takebox
@@ -93,7 +94,6 @@ local getprop = nuts.getprop
local nodecodes = nodes.nodecodes
local listcodes = nodes.listcodes
-local gluecodes = nodes.gluecodes
local whatsitcodes = nodes.whatsitcodes
local hlist_code = nodecodes.hlist
@@ -103,17 +103,17 @@ local userdefined_code = whatsitcodes.userdefined
local nodepool = nuts.pool
-local new_usernumber = nodepool.usernumber
+local new_usernode = nodepool.usernode
local new_hlist = nodepool.hlist
-local lateluafunction = nodepool.lateluafunction
+local latelua = nodepool.latelua
local texgetdimen = tex.getdimen
local texgetcount = tex.getcount
local texget = tex.get
local isleftpage = layouts.status.isleftpage
-local registertogether = builders.paragraphs.registertogether -- tonode
+local registertogether = builders.paragraphs.registertogether
local paragraphs = typesetters.paragraphs
local addtoline = paragraphs.addtoline
@@ -299,7 +299,9 @@ function margins.save(t)
--
-- t.realpageno = texgetcount("realpageno")
if inline then
- context(tonode(new_usernumber(inline_mark,nofsaved))) -- or use a normal node
+ local n = new_usernode(inline_mark,nofsaved)
+ setattrlist(n,true)
+ context(tonode(n)) -- or use a normal node
store[nofsaved] = t -- no insert
nofinlined = nofinlined + 1
else
@@ -448,8 +450,9 @@ end
-- anchors are only set for lines that have a note
-local function sa(tag) -- maybe l/r keys ipv left/right keys
- local p = cache[tag]
+local function sa(specification) -- maybe l/r keys ipv left/right keys
+ local tag = specification.tag
+ local p = cache[tag]
if p then
if trace_marginstack then
report_margindata("updating anchor %a",tag)
@@ -462,11 +465,13 @@ local function sa(tag) -- maybe l/r keys ipv left/right keys
end
local function setanchor(v_anchor) -- freezes the global here
- return lateluafunction(function() sa(v_anchor) end)
+ return latelua { action = sa, tag = v_anchor }
end
-local function aa(tag,n) -- maybe l/r keys ipv left/right keys
- local p = jobpositions.gettobesaved('md:v',tag)
+local function aa(specification) -- maybe l/r keys ipv left/right keys
+ local tag = specification.tag
+ local n = specification.n
+ local p = jobpositions.gettobesaved('md:v',tag)
if p then
if trace_marginstack then
report_margindata("updating injected %a",tag)
@@ -483,7 +488,7 @@ local function aa(tag,n) -- maybe l/r keys ipv left/right keys
end
local function addtoanchor(v_anchor,n) -- freezes the global here
- return lateluafunction(function() aa(v_anchor,n) end)
+ return latelua { action = aa, tag = v_anchor, n = n }
end
local function markovershoot(current) -- todo: alleen als offset > line
@@ -717,8 +722,8 @@ local function flushinline(parent,head)
while current and nofinlined > 0 do
local id = getid(current)
if id == whatsit_code then
- if getsubtype(current) == userdefined_code and getfield(current,"user_id") == inline_mark then
- local n = getfield(current,"value")
+ if getsubtype(current) == userdefined_code and getprop(current,"id") == inline_mark then
+ local n = getprop(current,"data")
local candidate = inlinestore[n]
if candidate then -- no vpack, as we want to realign
inlinestore[n] = nil
@@ -812,9 +817,8 @@ local function handler(scope,head,group)
if trace_margindata then
report_margindata("flushing stage one, stored %s, scope %s, delayed %s, group %a",nofstored,scope,nofdelayed,group)
end
- head = tonut(head)
local current = head
- local done = false
+ local done = false -- for tracing only
while current do
local id = getid(current)
if (id == vlist_code or id == hlist_code) and getprop(current,"margindata") == nil then
@@ -839,11 +843,9 @@ local function handler(scope,head,group)
report_margindata("flushing stage one, nothing done, %s left",nofstored)
end
end
-resetstacked()
- return tonode(head), done
- else
- return head, false
+ resetstacked()
end
+ return head
end
local trialtypesetting = context.trialtypesetting
@@ -854,7 +856,7 @@ local trialtypesetting = context.trialtypesetting
function margins.localhandler(head,group) -- sometimes group is "" which is weird
if trialtypesetting() then
- return head, false
+ return head
end
local inhibit = conditionals.inhibitmargindata
@@ -862,15 +864,15 @@ function margins.localhandler(head,group) -- sometimes group is "" which is weir
if trace_margingroup then
report_margindata("ignored 3, group %a, stored %s, inhibit %a",group,nofstored,inhibit)
end
- return head, false
- elseif nofstored > 0 then
+ return head
+ end
+ if nofstored > 0 then
return handler(v_local,head,group)
- else
- if trace_margingroup then
- report_margindata("ignored 4, group %a, stored %s, inhibit %a",group,nofstored,inhibit)
- end
- return head, false
end
+ if trace_margingroup then
+ report_margindata("ignored 4, group %a, stored %s, inhibit %a",group,nofstored,inhibit)
+ end
+ return head
end
function margins.globalhandler(head,group) -- check group
@@ -884,7 +886,7 @@ function margins.globalhandler(head,group) -- check group
if trace_margingroup then
report_margindata("ignored 1, group %a, stored %s, inhibit %a",group,nofstored,inhibit)
end
- return head, false
+ return head
elseif group == "hmode_par" then
return handler(v_global,head,group)
elseif group == "vmode_par" then -- experiment (for alignments)
@@ -899,22 +901,20 @@ function margins.globalhandler(head,group) -- check group
if trace_margingroup then
report_margindata("ignored 2, group %a, stored %s, inhibit %a",group,nofstored,inhibit)
end
- return head, false
+ return head
end
end
local function finalhandler(head)
if nofdelayed > 0 then
local current = head
- local done = false
- while current and nofdelayed > 0 do
+ while current and nofdelayed > 0 do -- traverse_list
local id = getid(current)
if id == hlist_code then -- only lines?
local a = getprop(current,"margindata")
if not a then
finalhandler(getlist(current))
elseif realigned(current,a) then
- done = true
if nofdelayed == 0 then
return head, true
end
@@ -924,10 +924,8 @@ local function finalhandler(head)
end
current = getnext(current)
end
- return head, done
- else
- return head, false
end
+ return head
end
function margins.finalhandler(head)
@@ -935,16 +933,12 @@ function margins.finalhandler(head)
if trace_margindata then
report_margindata("flushing stage two, instore: %s, delayed: %s",nofstored,nofdelayed)
end
- head = tonut(head)
- local head, done = finalhandler(head)
--- resetstacked(true)
-resetstacked(nofdelayed==0)
- head = tonode(head)
- return head, done
+ head = finalhandler(head)
+ resetstacked(nofdelayed==0)
else
resetstacked()
- return head, false
end
+ return head
end
-- Somehow the vbox builder (in combinations) gets pretty confused and decides to
@@ -996,6 +990,7 @@ interfaces.implement {
{ "align" },
{ "option" },
{ "line", "integer" },
+ { "index", "integer" },
{ "stackname" },
{ "stack" },
}
diff --git a/tex/context/base/mkiv/typo-mar.mkiv b/tex/context/base/mkiv/typo-mar.mkiv
index f265f173c..921f1f230 100644
--- a/tex/context/base/mkiv/typo-mar.mkiv
+++ b/tex/context/base/mkiv/typo-mar.mkiv
@@ -155,6 +155,7 @@
\forgetall
\tf
\resetallattributes % \deactivatecolor % needed, but maybe we should switch to maintextcolor: \onlyinheritmaintextcolor
+ \pickupattributes
\to \everymargindatacontent
% trialtypesetting: no need for margin stuff while trialing as
@@ -200,11 +201,17 @@
\let\margindatahbox\naturalhbox % \hbox
+\newcount\c_typo_margins_n
+
+\ifdefined\dotagmarginanchor \else \let\dotagmarginanchor\gobbleoneargument \fi
+\ifdefined\dotagmargintext \else \let\dotagmargintext \gobbleoneargument \fi
+
\unexpanded\def\typo_margins_data_yes_indeed[#dataparameters][#textparameters]#content%
{\iffirstargument
\setupcurrentmargindata[#dataparameters]%
\fi
\doifelsenothing{#content}\donefalse\donetrue
+ \global\advance\c_typo_margins_n\plusone
\ifdone
\edef\currentmarginreference{\margindataparameter\c!reference}%
\ifx\currentmarginreference\empty \else
@@ -212,6 +219,7 @@
\fi
\edef\currentmargindatastrut{\margindataparameter\c!strut}%
\dostarttaggedchained\t!margintext\currentmargindata\??margindata
+ \dotagmargintext\c_typo_margins_n
\ifcsname\currentmarginframedhash\s!parent\endcsname
\setbox\nextbox\margindatahbox \currentmarginreference \bgroup
\the\everymargindatacontent
@@ -271,6 +279,8 @@
\ifdone
\edef\p_anchor{\margindataparameter\c!anchor}%
\anch_positions_initialize % we use positions at the lua end
+ \dostarttagged\t!marginanchor\empty
+ \dotagmarginanchor\c_typo_margins_n
\clf_savemargindata
location {\margindataparameter\c!location}%
method {\margindataparameter\c!method}%
@@ -306,7 +316,9 @@
line \numexpr\margindataparameter\c!line\relax
stackname {\margindataparameter\c!stackname}%
stack {\margindataparameter\c!stack}%
+ index \c_typo_margins_n
\relax
+ \dostoptagged
\else
\clf_savemargindata
location {\margindataparameter\c!location}%
diff --git a/tex/context/base/mkiv/typo-pag.lua b/tex/context/base/mkiv/typo-pag.lua
index b5759a097..05513e20c 100644
--- a/tex/context/base/mkiv/typo-pag.lua
+++ b/tex/context/base/mkiv/typo-pag.lua
@@ -26,7 +26,6 @@ local unsetvalue = attributes.unsetvalue
local a_keeptogether = attributes.private("keeptogether")
local nuts = nodes.nuts
-local tonut = nuts.tonut
local getnext = nuts.getnext
local getprev = nuts.getprev
@@ -187,8 +186,8 @@ end
-- also look at first non glue/kern node e.g for a dropped caps
function parbuilders.keeptogether(head)
- local done = false
- local current = tonut(head)
+ local done = false
+ local current = head
while current do
if getid(current) == hlist_code then
local a = takeattr(current,a_keeptogether)
diff --git a/tex/context/base/mkiv/typo-par.mkiv b/tex/context/base/mkiv/typo-par.mkiv
index 3db0ffa45..066dc6a69 100644
--- a/tex/context/base/mkiv/typo-par.mkiv
+++ b/tex/context/base/mkiv/typo-par.mkiv
@@ -23,7 +23,7 @@
\unprotect
-\registerctxluafile{node-ltp}{}
+\registerctxluafile{node-ltp}{optimize}
\registerctxluafile{trac-par}{}
\protect \endinput
diff --git a/tex/context/base/mkiv/typo-pnc.lua b/tex/context/base/mkiv/typo-pnc.lua
index 1ed8d9940..732970884 100644
--- a/tex/context/base/mkiv/typo-pnc.lua
+++ b/tex/context/base/mkiv/typo-pnc.lua
@@ -9,7 +9,6 @@ if not modules then modules = { } end modules ['typo-pnc'] = {
local nodes = nodes
local fonts = fonts
-local prependaction = nodes.tasks.prependaction
local enableaction = nodes.tasks.enableaction
local nuts = nodes.nuts
@@ -23,7 +22,8 @@ local spaceskip_code = gluecodes.spaceskip
local new_kern = nuts.pool.kern
local insert_after = nuts.insert_after
-local traverse_id = nuts.traverse_id
+
+local nextglyph = nuts.traversers.glyph
local getchar = nuts.getchar
local getfont = nuts.getfont
@@ -68,10 +68,8 @@ local mapping = periodkerns.mapping
local factors = periodkerns.factors
function periodkerns.handler(head)
- local done = false
- local hnut = tonut(head)
- for current in traverse_id(glyph_code,tonut(hnut)) do
- if getchar(current) == period then
+ for current, char, font in nextglyph, head do
+ if char == period then
local a = getattr(current,a_periodkern)
if a then
local factor = mapping[a]
@@ -79,10 +77,10 @@ function periodkerns.handler(head)
local prev, next = getboth(current)
if prev and next and getid(prev) == glyph_code and getid(next) == glyph_code then
local pchar = getchar(prev)
- local pcode = categories[getchar(prev)]
+ local pcode = categories[pchar]
if pcode == "lu" or pcode == "ll" then
local nchar = getchar(next)
- local ncode = categories[getchar(next)]
+ local ncode = categories[nchar]
if ncode == "lu" or ncode == "ll" then
local next2 = getnext(next)
if next2 and getid(next2) == glyph_code and getchar(next2) == period then
@@ -91,11 +89,10 @@ function periodkerns.handler(head)
if factor ~= 0 then
fontspace = parameters[getfont(current)].space -- can be sped up
inserted = factor * fontspace
- insert_after(hnut,current,new_kern(inserted))
+ insert_after(head,current,new_kern(inserted))
if trace then
report("inserting space at %C . [%p] %C .",pchar,inserted,nchar)
end
- done = true
end
local next3 = getnext(next2)
if next3 and getid(next3) == glue_code and getsubtype(next3) == spaceskip_code then
@@ -115,7 +112,6 @@ function periodkerns.handler(head)
end
end
setwidth(next3,space)
- done = true
else
if trace then
if inserted then
@@ -136,7 +132,7 @@ function periodkerns.handler(head)
end
end
end
- return head, done
+ return head
end
local enabled = false
@@ -144,7 +140,6 @@ local enabled = false
function periodkerns.set(factor)
factor = tonumber(factor) or 0
if not enabled then
- prependaction("processors","normalizers","typesetters.periodkerns.handler")
enableaction("processors","typesetters.periodkerns.handler")
enabled = true
end
diff --git a/tex/context/base/mkiv/typo-rep.lua b/tex/context/base/mkiv/typo-rep.lua
index b6aae0cae..d29eb17b8 100644
--- a/tex/context/base/mkiv/typo-rep.lua
+++ b/tex/context/base/mkiv/typo-rep.lua
@@ -21,8 +21,6 @@ local nodes = nodes
local enableaction = nodes.tasks.enableaction
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local getnext = nuts.getnext
local getchar = nuts.getchar
@@ -81,9 +79,8 @@ local function process(what,head,current,char)
return head, current
end
-function nodes.handlers.stripping(head)
- head = tonut(head)
- local current, done = head, false
+function nodes.handlers.stripping(head) -- use loop
+ local current = head
while current do
local char, id = isglyph(current)
if char then
@@ -93,7 +90,6 @@ function nodes.handlers.stripping(head)
local what = glyphs[char]
if what then
head, current = process(what,head,current,char)
- done = true
else -- handling of spacing etc has to be done elsewhere
current = getnext(current)
end
@@ -104,7 +100,7 @@ function nodes.handlers.stripping(head)
current = getnext(current)
end
end
- return tonode(head), done
+ return head
end
local enabled = false
diff --git a/tex/context/base/mkiv/typo-rub.lua b/tex/context/base/mkiv/typo-rub.lua
index 8c41a5611..da63d7b64 100644
--- a/tex/context/base/mkiv/typo-rub.lua
+++ b/tex/context/base/mkiv/typo-rub.lua
@@ -33,8 +33,6 @@ local v_auto = variables.auto
local nuts = nodes.nuts
-local tonut = nodes.tonut
-local tonode = nodes.tonode
local getid = nuts.getid
local getsubtype = nuts.getsubtype
local getattr = nuts.getattr
@@ -53,7 +51,9 @@ local setwidth = nuts.setwidth
local hpack = nuts.hpack
local insert_after = nuts.insert_after
local takebox = nuts.takebox
-local traverse_id = nuts.traverse_id
+
+local nexthlist = nuts.traversers.hlist
+local nextvlist = nuts.traversers.vlist
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
@@ -63,14 +63,11 @@ local glue_code = nodecodes.glue
local penalty_code = nodecodes.penalty
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
-local whatsit_code = nodecodes.whatsit
local localpar_code = nodecodes.localpar
-
-local whatsitcodes = nodes.whatsitcodes
------ late_luacode = whatsitcodes.latelua
+local dir_code = nodecodes.dir
local kerncodes = nodes.kerncodes
-local font_code = kerncodes.font
+local fontkern_code = kerncodes.font
local nodepool = nuts.pool
local new_kern = nodepool.kern
@@ -194,7 +191,6 @@ do
end
function rubies.check(head)
- local head = tonut(head)
local current = head
local start = nil
local stop = nil
@@ -208,7 +204,7 @@ function rubies.check(head)
setprev(start)
setnext(stop)
local h = hpack(start)
- if prev == head then
+ if start == head then
head = h
else
setlink(prev,h)
@@ -247,20 +243,21 @@ function rubies.check(head)
start = current
stop = current
end
- elseif id == kern_code and getsubtype(current,font_code) then
+ -- go on
+ elseif id == kern_code and getsubtype(current,fontkern_code) then
-- go on
elseif found and id == disc_code then
-- go on (todo: look into disc)
elseif found then
- flush("flush 4")
+ flush("flush 3")
found = nil
end
current = nx
end
if found then
- flush("flush 5")
+ flush("flush 4")
end
- return tonode(head), true
+ return head, true -- no need for true
end
local attach
@@ -309,11 +306,11 @@ local function whatever(current)
local c = getprev(current)
while c do
local id = getid(c)
- if id == glue_code or id == penalty_code or id == kern_code or (id == whatsit_code and getsubtype(current,localpar_code)) then
+ if id == glue_code or id == penalty_code or id == kern_code then
-- go on
elseif id == hlist_code and getwidth(c) == 0 then
-- go on
- elseif id == whatsit_code or id == localpar_code then
+ elseif id == whatsit_code or id == localpar_code or id == dir_code then
-- go on
else
l = false
@@ -371,20 +368,17 @@ local function whatever(current)
end
end
-attach = function(head)
- for current in traverse_id(hlist_code,head) do
+attach = function(head) -- traverse_list
+ for current in nexthlist, head do
whatever(current)
end
- for current in traverse_id(vlist_code,head) do
+ for current in nextvlist, head do
whatever(current)
end
- return head, true
+ return head
end
-function rubies.attach(head)
- local h, d = attach(tonut(head))
- return tonode(h), d
-end
+rubies.attach = attach
-- for now there is no need to be compact
diff --git a/tex/context/base/mkiv/typo-rub.mkiv b/tex/context/base/mkiv/typo-rub.mkiv
index d51c53aa4..cc1571ad7 100644
--- a/tex/context/base/mkiv/typo-rub.mkiv
+++ b/tex/context/base/mkiv/typo-rub.mkiv
@@ -26,6 +26,7 @@
\installcorenamespace {ruby}
\installcorenamespace {rubyanalyze}
\installcorenamespace {rubyplacement}
+\installcorenamespace {rubynumber}
\installcommandhandler \??ruby {ruby} \??ruby
@@ -135,6 +136,14 @@
\c!hoffset=\zeropoint,
\c!voffset=-2\exheight]
+%D Experiment too:
+
+\unexpanded\def\numberedruby[#1]#2%
+ {\doifnotcounter{\??rubynumber#1}{\definecounter[\??rubynumber#1]\setcounter[\??rubynumber#1][1]}%
+ \ruby[#1]{#2}{\convertedcounter[\??rubynumber#1]}%
+ \incrementcounter[\??rubynumber#1]%
+ \relax}
+
\protect \endinput
% \usemodule[art-01]\setupbodyfont[dejavu,12pt]
diff --git a/tex/context/base/mkiv/typo-scr.mkiv b/tex/context/base/mkiv/typo-scr.mkiv
index d4881b80a..0dfd111ae 100644
--- a/tex/context/base/mkiv/typo-scr.mkiv
+++ b/tex/context/base/mkiv/typo-scr.mkiv
@@ -142,8 +142,8 @@
\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}}%
+ \setbox\plusfour\hpack{\typo_scripts_lowhigh_low_high\lower\c!down\t!sub{#2}}%
+ \setbox\plussix \hpack{\typo_scripts_lowhigh_low_high\raise\c!up \t!sup{#3}}%
\doif{#1}{\v!left}
{\ifdim\wd\plusfour<\wd\plussix
\setbox\plusfour\hpack to \wd\plussix {\hss\box\plusfour}%
@@ -166,7 +166,7 @@
{\dontleavehmode
\begingroup
\kern\lowhighparameter\c!distance\relax
- \setbox\scratchbox\hbox\bgroup
+ \setbox\scratchbox\hpack\bgroup
#1\lowhighparameter#2\hbox\bgroup
\ifx\fontsize\empty
\ifmmode
diff --git a/tex/context/base/mkiv/typo-spa.lua b/tex/context/base/mkiv/typo-spa.lua
index bda139719..78fc22964 100644
--- a/tex/context/base/mkiv/typo-spa.lua
+++ b/tex/context/base/mkiv/typo-spa.lua
@@ -23,12 +23,9 @@ local unsetvalue = attributes.unsetvalue
local v_reset = interfaces.variables.reset
local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
local getnext = nuts.getnext
local getprev = nuts.getprev
-local getfont = nuts.getfont
local takeattr = nuts.takeattr
local isglyph = nuts.isglyph
@@ -73,8 +70,6 @@ end
-- todo cache lastattr
function spacings.handler(head)
- head = tonut(head)
- local done = false
local start = head
-- head is always begin of par (whatsit), so we have at least two prev nodes
-- penalty followed by glue
@@ -87,10 +82,11 @@ function spacings.handler(head)
if data then
local map = data.characters[char]
if map then
+ local font = id
local left = map.left
local right = map.right
local alternative = map.alternative
- local quad = quaddata[getfont(start)]
+ local quad = quaddata[font]
local prev = getprev(start)
if left and left ~= 0 and prev then
local ok = false
@@ -122,7 +118,6 @@ function spacings.handler(head)
end
insert_node_before(head,start,new_penalty(10000))
insert_node_before(head,start,new_glue(left*quad))
- done = true
end
end
local next = getnext(start)
@@ -159,7 +154,6 @@ function spacings.handler(head)
end
insert_node_after(head,start,new_glue(right*quad))
insert_node_after(head,start,new_penalty(10000))
- done = true
end
end
end
@@ -172,7 +166,7 @@ function spacings.handler(head)
start = getnext(start)
end
end
- return tonode(head), done
+ return head
end
local enabled = false
diff --git a/tex/context/base/mkiv/typo-sus.lua b/tex/context/base/mkiv/typo-sus.lua
index 2d3037bdc..6c02b9291 100644
--- a/tex/context/base/mkiv/typo-sus.lua
+++ b/tex/context/base/mkiv/typo-sus.lua
@@ -40,8 +40,6 @@ local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local nuts = nodes.nuts
-local tonut = nodes.tonut
-local tonode = nodes.tonode
local getid = nuts.getid
local getprev = nuts.getprev
@@ -164,7 +162,6 @@ local colors = {
local found = 0
function typesetters.marksuspects(head)
- local head = tonut(head)
local current = head
local lastdone = nil
while current do
@@ -254,7 +251,7 @@ function typesetters.marksuspects(head)
current = getnext(current)
end
end
- return tonode(head), found > 0
+ return head
end
local function showsuspects(head)
@@ -289,9 +286,9 @@ end
function typesetters.showsuspects(head)
if found > 0 then
- return tonode(showsuspects(tonut(head))), true
+ return showsuspects(head)
else
- return head, false
+ return head
end
end
diff --git a/tex/context/base/mkiv/typo-tal.lua b/tex/context/base/mkiv/typo-tal.lua
index 870d006cc..8cf298329 100644
--- a/tex/context/base/mkiv/typo-tal.lua
+++ b/tex/context/base/mkiv/typo-tal.lua
@@ -34,7 +34,6 @@ local v_number = variables.number
local nuts = nodes.nuts
local tonut = nuts.tonut
-local tonode = nuts.tonode
local getnext = nuts.getnext
local getprev = nuts.getprev
@@ -50,8 +49,8 @@ local setchar = nuts.setchar
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
-local traverse_list_by_id = nuts.traverse_id
-local list_dimensions = nuts.dimensions
+local nextglyph = nuts.traversers.glyph
+local getdimensions = nuts.dimensions
local first_glyph = nuts.first_glyph
local setglue = nuts.setglue
@@ -171,23 +170,22 @@ local function traced_kern(w)
return tracedrule(w,nil,nil,"darkgray")
end
-function characteralign.handler(originalhead,where)
+function characteralign.handler(head,where)
if not datasets then
- return originalhead, false
+ return head
end
- local head = tonut(originalhead)
-- local first = first_glyph(head) -- we could do that once
local first
- for n in traverse_list_by_id(glyph_code,head) do
+ for n in nextglyph, head do
first = n
break
end
if not first then
- return originalhead, false
+ return head
end
local a = getattr(first,a_characteralign)
if not a or a == 0 then
- return originalhead, false
+ return head
end
local column = div(a,0xFFFF)
local row = a % 0xFFFF
@@ -210,7 +208,7 @@ function characteralign.handler(originalhead,where)
while current do
local char, id = isglyph(current)
if char then
- local font = getfont(current)
+ local font = id --- nicer
local data = fontcharacters[font][char]
local unicode = data and data.unicode or char -- ignore tables
if not unicode then -- type(unicode) ~= "number"
@@ -234,8 +232,9 @@ function characteralign.handler(originalhead,where)
if not b_start then
if sign then
b_start = sign
- local new = validsigns[getchar(sign)]
- if char == new or not fontcharacters[getfont(sign)][new] then
+ local c, f = isglyph(sign)
+ local new = validsigns[c]
+ if char == new or not fontcharacters[f][new] then
if trace_split then
setcolor(sign,"darkyellow")
end
@@ -285,7 +284,7 @@ function characteralign.handler(originalhead,where)
while current do
local char, id = isglyph(current)
if char then
- local font = getfont(current)
+ local font = id -- nicer
-- local unicode = unicodes[font][char]
local unicode = fontcharacters[font][char].unicode or char -- ignore tables
if not unicode then
@@ -322,21 +321,21 @@ function characteralign.handler(originalhead,where)
local predefined = dataset.predefined
local before, after
if predefined then
- before = b_start and list_dimensions(b_start,getnext(b_stop)) or 0
- after = a_start and list_dimensions(a_start,getnext(a_stop)) or 0
+ before = b_start and getdimensions(b_start,getnext(b_stop)) or 0
+ after = a_start and getdimensions(a_start,getnext(a_stop)) or 0
else
local entry = list[row]
if entry then
before = entry.before or 0
after = entry.after or 0
else
- before = b_start and list_dimensions(b_start,getnext(b_stop)) or 0
- after = a_start and list_dimensions(a_start,getnext(a_stop)) or 0
+ before = b_start and getdimensions(b_start,getnext(b_stop)) or 0
+ after = a_start and getdimensions(a_start,getnext(a_stop)) or 0
list[row] = {
before = before,
after = after,
}
- return tonode(head), true
+ return head, true
end
if not dataset.collected then
-- print("[maxbefore] [maxafter]")
@@ -404,5 +403,5 @@ function characteralign.handler(originalhead,where)
insert_node_after(head,c,new_kern(maxafter))
end
end
- return tonode(head), true
+ return head
end
diff --git a/tex/context/base/mkiv/typo-wrp.lua b/tex/context/base/mkiv/typo-wrp.lua
index 07e34cd6c..9fb544152 100644
--- a/tex/context/base/mkiv/typo-wrp.lua
+++ b/tex/context/base/mkiv/typo-wrp.lua
@@ -8,65 +8,80 @@ if not modules then modules = { } end modules ['typo-wrp'] = {
-- begin/end par wrapping stuff ... more to come
-local nodecodes = nodes.nodecodes
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+local penaltycodes = nodes.penaltycodes
+local boundarycodes = nodes.boundarycodes
-local glue_code = nodecodes.glue
-local penalty_code = nodecodes.penalty
-local parfill_skip_code = nodes.gluecodes.parfillskip
-local user_penalty_code = nodes.penaltycodes.userpenalty
+local glue_code = nodecodes.glue
+local penalty_code = nodecodes.penalty
+local boundary_code = nodecodes.boundary
-local nuts = nodes.nuts
-local tonut = nodes.tonut
-local tonode = nodes.tonode
+local parfillskip_code = gluecodes.parfillskip
-local find_node_tail = nuts.tail
-local getprev = nuts.getprev
-local getid = nuts.getid
-local getsubtype = nuts.getsubtype
-local getpenalty = nuts.getpenalty
-local remove = nuts.remove
+local userpenalty_code = penaltycodes.userpenalty
+local linepenalty_code = penaltycodes.linepenalty
+local linebreakpenalty_code = penaltycodes.linebreakpenalty
-local enableaction = nodes.tasks.enableaction
+local wordboundary_code = boundarycodes.word
-local wrappers = { }
-typesetters.wrappers = wrappers
+local nuts = nodes.nuts
-local trace_wrappers = trackers.register("typesetters.wrappers",function(v) trace_wrappers = v end)
+local find_node_tail = nuts.tail
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getsubtype = nuts.getsubtype
+local getpenalty = nuts.getpenalty
+local remove = nuts.remove
-local report = logs.reporter("paragraphs","wrappers")
+local enableaction = nodes.tasks.enableaction
+
+local wrappers = { }
+typesetters.wrappers = wrappers
+
+local trace_wrappers = trackers.register("typesetters.wrappers",function(v) trace_wrappers = v end)
+
+local report = logs.reporter("paragraphs","wrappers")
-- we really need to pass tail too ... but then we need to check all the plugins
-- bah ... slowdown
+-- This check is very tight to the crlf definition. We check for:
+--
+-- [break -10000] [wordboundary] [line(break)penalty] [parfillskip]
+--
+-- If needed we can extend this checker for other cases but then we will also
+-- use attributes.
+
local function remove_dangling_crlf(head,tail)
- if tail and getid(tail) == glue_code and getsubtype(tail) == parfill_skip_code then
+ if head and tail and getid(tail) == glue_code and getsubtype(tail) == parfillskip_code then
tail = getprev(tail)
- if tail and getid(tail) == penalty_code and getsubtype(tail) == user_penalty_code and getpenalty(tail) == 10000 then
- tail = getprev(tail)
- if tail and getid(tail) == penalty_code and getsubtype(tail) == user_penalty_code and getpenalty(tail) == -10000 then
- if tail == head then
- -- can't happen
- else
- if trace_wrappers then
- report("removing a probably unwanted end-of-par break in line %s (guess)",tex.inputlineno)
+ if tail and getid(tail) == penalty_code then
+ local subtype = getsubtype(tail)
+ if subtype == linepenalty_code or subtype == linebreakpenalty_code then
+ tail = getprev(tail)
+ if tail and getid(tail) == boundary_code and getsubtype(tail) == wordboundary_code then
+ tail = getprev(tail)
+ if tail ~= head and getid(tail) == penalty_code and getsubtype(tail) == userpenalty_code and getpenalty(tail) == -10000 then
+ if trace_wrappers then
+ report("removing a probably unwanted end-of-par break in line %s (guess)",tex.inputlineno)
+ end
+ remove(head,tail,true)
+ return head, tail
end
- remove(head,tail,true)
- return head, tail, true
end
end
end
end
- return head, tail, false
+ return head, tail
end
function wrappers.handler(head)
- local head = tonut(head)
if head then
local tail = find_node_tail(head)
- local done = false
- head, tail, done = remove_dangling_crlf(head,tail) -- will be action chain
+ head, tail = remove_dangling_crlf(head,tail) -- will be action chain
end
- return head, true
+ return head
end
interfaces.implement {
diff --git a/tex/context/base/mkiv/typo-wrp.mkiv b/tex/context/base/mkiv/typo-wrp.mkiv
index 0e010515b..4e9ecf2e1 100644
--- a/tex/context/base/mkiv/typo-wrp.mkiv
+++ b/tex/context/base/mkiv/typo-wrp.mkiv
@@ -40,18 +40,21 @@
\unexpanded\def\spac_crlf
{\clf_enablecrlf % once
\unskip
- \prewordbreak % here or in \spac_crlf_placeholder
\spac_crlf_placeholder
\ifcase\raggedstatus\hfil\or\or\or\hfil\fi
+ % in bad usage this can lead to: [break -10000] [wordboundary] [line(break)penalty] [parfillskip]
\break
- \hskip\zeropoint % new so that the next word also hyphenates
+ \wordboundary
+ % which we then remove (maybe we should flag the wordboundary with an attribute but not now
\ignorespaces}
\unexpanded\def\spac_crlf_placeholder
{\strut}
\unexpanded\def\spac_crlf_placeholder_show
- {\hbox to \zeropoint{\strut{\infofont\kern.25\emwidth}\lohi{\infofont CR}{\infofont LF}\hss}}
+ {\wordboundary
+ %\nobreak
+ \hpack to \zeropoint{\strut{\infofont\kern.25\emwidth}\lohi{\infofont CR}{\infofont LF}\hss}}
\unexpanded\def\settestcrlf
{\let\spac_crlf_placeholder\spac_crlf_placeholder_show}
diff --git a/tex/context/base/mkiv/util-deb.lua b/tex/context/base/mkiv/util-deb.lua
index b8db0c583..6932e8804 100644
--- a/tex/context/base/mkiv/util-deb.lua
+++ b/tex/context/base/mkiv/util-deb.lua
@@ -10,9 +10,6 @@ if not modules then modules = { } end modules ['util-deb'] = {
-- bound to a variable, like node.new, node.copy etc (contrary to for instance
-- node.has_attribute which is bound to a has_attribute local variable in mkiv)
-local debug = require "debug"
-
-local getinfo, sethook = debug.getinfo, debug.sethook
local type, next, tostring, tonumber = type, next, tostring, tonumber
local format, find, sub, gsub = string.format, string.find, string.sub, string.gsub
local insert, remove, sort = table.insert, table.remove, table.sort
@@ -98,7 +95,7 @@ end
setmetatableindex(names,function(t,name)
local v = setmetatableindex(function(t,source)
local v = setmetatableindex(function(t,line)
- local v = { total = 0, count = 0 }
+ local v = { total = 0, count = 0, nesting = 0 }
t[line] = v
return v
end)
@@ -109,6 +106,9 @@ setmetatableindex(names,function(t,name)
return v
end)
+local getinfo = nil
+local sethook = nil
+
local function hook(where)
local f = getinfo(2,"nSl")
if f then
@@ -128,12 +128,24 @@ local function hook(where)
end
local data = names[name][source][line]
if where == "call" then
- data.count = data.count + 1
- insert(data,ticks())
+ local nesting = data.nesting
+ if nesting == 0 then
+ data.count = data.count + 1
+ insert(data,ticks())
+ data.nesting = 1
+ else
+ data.nesting = nesting + 1
+ end
elseif where == "return" then
- local t = remove(data)
- if t then
- data.total = data.total + ticks() - t
+ local nesting = data.nesting
+ if nesting == 1 then
+ local t = remove(data)
+ if t then
+ data.total = data.total + ticks() - t
+ end
+ data.nesting = 0
+ else
+ data.nesting = nesting - 1
end
end
end
@@ -228,6 +240,27 @@ function debugger.showstats(printer,threshold)
-- table.save("luatex-profile.lua",names)
end
+local function getdebug()
+ if sethook and getinfo then
+ return
+ end
+ if not debug then
+ local okay
+ okay, debug = pcall(require,"debug")
+ end
+ if type(debug) ~= "table" then
+ return
+ end
+ getinfo = debug.getinfo
+ sethook = debug.sethook
+ if type(getinfo) ~= "function" then
+ getinfo = nil
+ end
+ if type(sethook) ~= "function" then
+ sethook = nil
+ end
+end
+
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -237,7 +270,8 @@ function debugger.savestats(filename,threshold)
end
function debugger.enable()
- if nesting == 0 then
+ getdebug()
+ if sethook and getinfo and nesting == 0 then
running = true
if initialize then
initialize()
@@ -259,7 +293,7 @@ function debugger.disable()
if nesting > 0 then
nesting = nesting - 1
end
- if nesting == 0 then
+ if sethook and getinfo and nesting == 0 then
sethook()
end
end
@@ -282,20 +316,25 @@ end
-- from the lua book:
local function showtraceback(rep) -- from lua site / adapted
- local level = 2 -- we don't want this function to be reported
- local reporter = rep or report
- while true do
- local info = getinfo(level, "Sl")
- if not info then
- break
- elseif info.what == "C" then
- reporter("%2i : %s",level-1,"C function")
- else
- reporter("%2i : %s : %s",level-1,info.short_src,info.currentline)
+ getdebug()
+ if getinfo then
+ local level = 2 -- we don't want this function to be reported
+ local reporter = rep or report
+ while true do
+ local info = getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ reporter("%2i : %s",level-1,"C function")
+ else
+ reporter("%2i : %s : %s",level-1,info.short_src,info.currentline)
+ end
+ level = level + 1
end
- level = level + 1
end
end
debugger.showtraceback = showtraceback
-- debug.showtraceback = showtraceback
+
+-- showtraceback()
diff --git a/tex/context/base/mkiv/util-env.lua b/tex/context/base/mkiv/util-env.lua
index 064bd513a..dde765874 100644
--- a/tex/context/base/mkiv/util-env.lua
+++ b/tex/context/base/mkiv/util-env.lua
@@ -72,20 +72,16 @@ end
-- dirty tricks (we will replace the texlua call by luatex --luaonly)
local validengines = allocate {
- ["luatex"] = true,
- ["luajittex"] = true,
- -- ["luatex.exe"] = true,
- -- ["luajittex.exe"] = true,
+ ["luatex"] = true,
+ ["luajittex"] = true,
}
local basicengines = allocate {
- ["luatex"] = "luatex",
- ["texlua"] = "luatex",
- ["texluac"] = "luatex",
- ["luajittex"] = "luajittex",
- ["texluajit"] = "luajittex",
- -- ["texlua.exe"] = "luatex",
- -- ["texluajit.exe"] = "luajittex",
+ ["luatex"] = "luatex",
+ ["texlua"] = "luatex", -- obsolete
+ ["texluac"] = "luatex", -- obsolete
+ ["luajittex"] = "luajittex",
+ ["texluajit"] = "luajittex", -- obsolete
}
local luaengines = allocate {
@@ -154,8 +150,11 @@ environment.sortedflags = nil
-- 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
+ local arguments = { }
+ local files = { }
+ environment.arguments = arguments
+ environment.files = files
+ environment.sortedflags = nil
for index=1,#arg do
local argument = arg[index]
if index > 0 then
@@ -174,6 +173,11 @@ function environment.initializearguments(arg)
end
end
end
+ if not environment.ownname then
+ if os.selfpath and os.selfname then
+ environment.ownname = file.addsuffix(file.join(os.selfpath,os.selfname),"lua")
+ end
+ end
environment.ownname = file.reslash(environment.ownname or arg[0] or 'unknown.lua')
end
@@ -281,13 +285,20 @@ if arg then
for index=1,#arg do
local argument = arg[index]
if find(argument,"^\"") then
- newarg[#newarg+1] = gsub(argument,"^\"","")
- if not find(argument,"\"$") then
+ if find(argument,"\"$") then
+ newarg[#newarg+1] = gsub(argument,"^\"(.-)\"$","%1")
+ instring = false
+ else
+ newarg[#newarg+1] = gsub(argument,"^\"","")
instring = true
end
elseif find(argument,"\"$") then
- newarg[#newarg] = newarg[#newarg] .. " " .. gsub(argument,"\"$","")
- instring = false
+ if instring then
+ newarg[#newarg] = newarg[#newarg] .. " " .. gsub(argument,"\"$","")
+ instring = false
+ else
+ newarg[#newarg+1] = argument
+ end
elseif instring then
newarg[#newarg] = newarg[#newarg] .. " " .. argument
else
diff --git a/tex/context/base/mkiv/util-evo.lua b/tex/context/base/mkiv/util-evo.lua
index 7f0b59ac4..dfb395e08 100644
--- a/tex/context/base/mkiv/util-evo.lua
+++ b/tex/context/base/mkiv/util-evo.lua
@@ -161,15 +161,22 @@ local function loadedtable(filename)
for i=1,10 do
local t = loadtable(filename)
if t then
+ report("file %a loaded",filename)
return t
else
ossleep(1/4)
end
end
end
+ report("file %a not loaded",filename)
return { }
end
+local function savedtable(filename,data)
+ savetable(filename,data)
+ report("file %a saved",filename)
+end
+
local function loadpresets(filename)
local presets = loadtable(filename)
if presets then
@@ -194,6 +201,13 @@ local function loadeverything(filename)
return loadedtable(filename)
end
+local function loadlatest(filename)
+ if type(filename) == "table" and validpresets(filename) then
+ filename = filename.files and filename.files.latest
+ end
+ return loadedtable(filename)
+end
+
local function result(t,fmt,a,b,c)
if t then
report(fmt,a or "done",b or "done",c or "done","done")
@@ -365,6 +379,21 @@ local function findzone(presets,name)
return usedzones and usedzones[name]
end
+local function getzonenames(presets)
+ if not presets then
+ return { }
+ end
+ local data = presets.data
+ if not data then
+ return { }
+ end
+ local t = sortedkeys(data.zones or { })
+ for i=1,#t do
+ t[i] = lower(t[i])
+ end
+ return t
+end
+
local function gettargets(zone) -- maybe also for a day
local schedule = zone.schedule
local min = false
@@ -503,7 +532,7 @@ local function geteverything(presets,noschedules)
end
end
end
- savetable(presets.files.everything,data)
+ savedtable(presets.files.everything,data)
return result(data,"getting everything, %s")
end
end
@@ -521,26 +550,29 @@ local function gettemperatures(presets)
for i=1,#data do
local gateways = data[i].gateways
local locationinfo = data[i].locationInfo
- local locationid = locationinfo.locationId
- if gateways then
- local status = getstatus(presets,locationid,locationinfo.name)
- if status then
- for i=1,#gateways do
- local g = status.gateways[i]
- local gateway = gateways[i]
- local systems = gateway.temperatureControlSystems
- if systems then
- local s = g.temperatureControlSystems
- for i=1,#systems do
- local zones = systems[i].zones
- if zones then
- local z = s[i].zones
- for i=1,#zones do
- if validzonetypes[zone.zoneType] then
- local z = z[i]
- if z.name == zone.name then
- zone.temperatureStatus = z.temperatureStatus
- updated = true
+ if locationinfo then
+ local locationid = locationinfo.locationId
+ if gateways then
+ local status = getstatus(presets,locationid,locationinfo.name)
+ if status then
+ for i=1,#gateways do
+ local g = status.gateways[i]
+ local gateway = gateways[i]
+ local systems = gateway.temperatureControlSystems
+ if systems then
+ local s = g.temperatureControlSystems
+ for i=1,#systems do
+ local zones = systems[i].zones
+ if zones then
+ local z = s[i].zones
+ for i=1,#zones do
+ local zone = zones[i]
+ if validzonetypes[zone.zoneType] then
+ local z = z[i]
+ if z.name == zone.name then
+ zone.temperatureStatus = z.temperatureStatus
+ updated = true
+ end
end
end
end
@@ -548,12 +580,16 @@ local function gettemperatures(presets)
end
end
end
+ else
+ report("no gateways")
end
+ else
+ report("no location info")
end
end
if updated then
data.time = ostime()
- savetable(presets.files.latest,data)
+ savedtable(presets.files.latest,data)
end
return result(data,"getting temperatures, %s")
end
@@ -601,7 +637,10 @@ end
local function loadtemperatures(presets)
if validpresets(presets) then
- local status = loadeverything(presets)
+ local status = loadlatest(presets)
+ if not status or not next(status) then
+ status = loadeverything(presets)
+ end
if status then
local usedgateways = presets.data.gateways
for i=1,#status do
@@ -637,9 +676,10 @@ end
local function updatetemperatures(presets)
if validpresets(presets) then
local everythingname = presets.files.everything
+ local latestname = presets.files.latest
local historyname = presets.files.history
- if everythingname and historyname then
- gettemperatures(presets,everythingname)
+ if (everythingname or latestname) and historyname then
+ gettemperatures(presets)
local t = loadtemperatures(presets)
if t then
local data = { }
@@ -649,7 +689,7 @@ local function updatetemperatures(presets)
end
local history = loadhistory(historyname) or { }
setmoment(history,ostime(),data)
- savetable(historyname,history)
+ savedtable(historyname,history)
return result(t,"updating temperatures, %s")
end
end
@@ -747,10 +787,10 @@ local function off(presets,name)
end
end
-local function on(presets,name)
+local function on(presets,name,temperature)
local zone = presets and getzonestate(presets,name)
if zone then
- setzonestate(presets,name,zone.highest)
+ setzonestate(presets,name,temperature or zone.highest)
end
end
@@ -787,7 +827,7 @@ local function settask(presets,when,tag,action)
else
list[tag] = nil
end
- savetable(presets.files.schedules,list)
+ savedtable(presets.files.schedules,list)
end
end
@@ -832,7 +872,7 @@ local function checktasks(presets)
for k, v in next, q do
list[q] = nil
end
- savetable(presets.files.schedules,list)
+ savedtable(presets.files.schedules,list)
end
return list
end
@@ -954,10 +994,10 @@ end
evohome = {
helpers = {
- getaccesstoken = getaccesstoken, -- presets
- getuserinfo = getuserinfo, -- presets
- getlocationinfo = getlocationinfo, -- presets
- getschedule = getschedule, -- presets, name
+ getaccesstoken = getaccesstoken, -- presets
+ getuserinfo = getuserinfo, -- presets
+ getlocationinfo = getlocationinfo, -- presets
+ getschedule = getschedule, -- presets, name
--
geteverything = geteverything, -- presets, noschedules
gettemperatures = gettemperatures, -- presets
@@ -965,6 +1005,7 @@ evohome = {
setzonestate = setzonestate, -- presets, name, temperature
resetzonestate = resetzonestate, -- presets, name
getzonedata = findzone, -- presets, name
+ getzonenames = getzonenames, -- presets
--
loadpresets = loadpresets, -- filename
loadhistory = loadhistory, -- presets | filename
diff --git a/tex/context/base/mkiv/util-fil.lua b/tex/context/base/mkiv/util-fil.lua
index 0e8ed4e57..9f96a01b9 100644
--- a/tex/context/base/mkiv/util-fil.lua
+++ b/tex/context/base/mkiv/util-fil.lua
@@ -6,6 +6,7 @@ if not modules then modules = { } end modules ['util-fil'] = {
license = "see context related readme files"
}
+local tonumber = tonumber
local byte = string.byte
local char = string.char
@@ -196,41 +197,23 @@ function files.readinteger4le(f)
end
end
--- function files.readfixed2(f)
--- local a, b = byte(f:read(2),1,2)
--- if a >= 0x80 then
--- return (0x100 * a + b - 0x10000)/256.0
--- else
--- return (0x100 * a + b)/256.0
--- end
--- end
-
function files.readfixed2(f)
local a, b = byte(f:read(2),1,2)
if a >= 0x80 then
- return (a - 0x100) + b/0x100
+ tonumber((a - 0x100) .. "." .. b)
else
- return (a ) + b/0x100
+ tonumber(( a ) .. "." .. b)
end
end
--- (real) (n>>16) + ((n&0xffff)/65536.0))
-
--- function files.readfixed4(f)
--- local a, b, c, d = byte(f:read(4),1,4)
--- if a >= 0x80 then
--- return (0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000)/65536.0
--- else
--- return (0x1000000 * a + 0x10000 * b + 0x100 * c + d)/65536.0
--- end
--- end
+-- (real) (n>>16) + ((n&0xffff)/65536.0)) but no cast in lua (we could use unpack)
function files.readfixed4(f)
local a, b, c, d = byte(f:read(4),1,4)
if a >= 0x80 then
- return (0x100 * a + b - 0x10000) + (0x100 * c + d)/0x10000
+ tonumber((0x100 * a + b - 0x10000) .. "." .. (0x100 * c + d))
else
- return (0x100 * a + b ) + (0x100 * c + d)/0x10000
+ tonumber((0x100 * a + b ) .. "." .. (0x100 * c + d))
end
end
@@ -343,3 +326,40 @@ if fio and fio.readcardinal1 then
end
end
+
+if fio and fio.readcardinaltable then
+
+ files.readcardinaltable = fio.readcardinaltable
+ files.readintegertable = fio.readintegertable
+
+else
+
+ local readcardinal1 = files.readcardinal1
+ local readcardinal2 = files.readcardinal2
+ local readcardinal3 = files.readcardinal3
+ local readcardinal4 = files.readcardinal4
+
+ function files.readcardinaltable(f,n,b)
+ local t = { }
+ if b == 1 then for i=1,n do t[i] = readcardinal1(f) end
+ elseif b == 2 then for i=1,n do t[i] = readcardinal2(f) end
+ elseif b == 3 then for i=1,n do t[i] = readcardinal3(f) end
+ elseif b == 4 then for i=1,n do t[i] = readcardinal4(f) end end
+ return t
+ end
+
+ local readinteger1 = files.readinteger1
+ local readinteger2 = files.readinteger2
+ local readinteger3 = files.readinteger3
+ local readinteger4 = files.readinteger4
+
+ function files.readintegertable(f,n,b)
+ local t = { }
+ if b == 1 then for i=1,n do t[i] = readinteger1(f) end
+ elseif b == 2 then for i=1,n do t[i] = readinteger2(f) end
+ elseif b == 3 then for i=1,n do t[i] = readinteger3(f) end
+ elseif b == 4 then for i=1,n do t[i] = readinteger4(f) end end
+ return t
+ end
+
+end
diff --git a/tex/context/base/mkiv/util-fmt.lua b/tex/context/base/mkiv/util-fmt.lua
index 371a5dfce..fe80c6420 100644
--- a/tex/context/base/mkiv/util-fmt.lua
+++ b/tex/context/base/mkiv/util-fmt.lua
@@ -35,10 +35,17 @@ function formatters.formatcolumns(result,between)
for j=1,n do
local rj = r[j]
local tj = type(rj)
+-- if tj == "number" then
+-- numbers[j] = true
+-- end
+-- if tj ~= "string" then
+-- rj = tostring(rj)
+-- r[j] = rj
+-- end
if tj == "number" then
numbers[j] = true
- end
- if tj ~= "string" then
+ rj = tostring(rj)
+ elseif tj ~= "string" then
rj = tostring(rj)
r[j] = rj
end
diff --git a/tex/context/base/mkiv/util-jsn.lua b/tex/context/base/mkiv/util-jsn.lua
index e5f83e06c..acbf16090 100644
--- a/tex/context/base/mkiv/util-jsn.lua
+++ b/tex/context/base/mkiv/util-jsn.lua
@@ -14,10 +14,12 @@ if not modules then modules = { } end modules ['util-jsn'] = {
--
-- Reminder for me: check usage in framework and extend when needed. Also document
-- it in the cld lib documentation.
+--
+-- Upgraded for handling the somewhat more fax server templates.
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 format, gsub = string.format, string.gsub
local utfchar = utf.char
local concat = table.concat
@@ -26,9 +28,6 @@ local tonumber, tostring, rawset, type, next = 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("{")
@@ -43,16 +42,19 @@ local whitespace = lpeg.patterns.whitespace
local optionalws = whitespace^0
local escapes = {
- -- ["\\"] = "\\", -- lua will escape these
- -- ["/"] = "/", -- no need to escape this one
- ["b"] = "\010",
- ["f"] = "\014",
- ["n"] = "\n",
- ["r"] = "\r",
- ["t"] = "\t",
+ ["b"] = "\010",
+ ["f"] = "\014",
+ ["n"] = "\n",
+ ["r"] = "\r",
+ ["t"] = "\t",
}
-local escape_un = C(P("\\u") / "0x" * S("09","AF","af")) / function(s) return utfchar(tonumber(s)) end
+-- todo: also handle larger utf16
+
+local escape_un = P("\\u")/"" * (C(R("09","AF","af")^-4) / function(s)
+ return utfchar(tonumber(s,16))
+end)
+
local escape_bs = P([[\]]) / "" * (P(1) / escapes) -- if not found then P(1) is returned i.e. the to be escaped char
local jstring = dquote * Cs((escape_un + escape_bs + (1-dquote))^0) * dquote
@@ -85,7 +87,9 @@ function json.tolua(str)
return lpegmatch(jsonconverter,str)
end
-local function tojson(value,t) -- we could optimize #t
+local escaper
+
+local function tojson(value,t,n) -- we could optimize #t
local kind = type(value)
if kind == "table" then
local done = false
@@ -93,60 +97,75 @@ local function tojson(value,t) -- we could optimize #t
if size == 0 then
for k, v in next, value do
if done then
- t[#t+1] = ","
+ n = n + 1 ; t[n] = ","
else
- t[#t+1] = "{"
+ n = n + 1 ; t[n] = "{"
done = true
end
- t[#t+1] = format("%q:",k)
- tojson(v,t)
+ n = n + 1 ; t[n] = format("%q:",k)
+ t, n = tojson(v,t,n)
end
if done then
- t[#t+1] = "}"
+ n = n + 1 ; t[n] = "}"
else
- t[#t+1] = "{}"
+ n = n + 1 ; t[n] = "{}"
end
elseif size == 1 then
-- we can optimize for non tables
- t[#t+1] = "["
- tojson(value[1],t)
- t[#t+1] = "]"
+ n = n + 1 ; t[n] = "["
+ t, n = tojson(value[1],t,n)
+ n = n + 1 ; t[n] = "]"
else
for i=1,size do
if done then
- t[#t+1] = ","
+ n = n + 1 ; t[n] = ","
else
- t[#t+1] = "["
+ n = n + 1 ; t[n] = "["
done = true
end
- tojson(value[i],t)
+ t, n = tojson(value[i],t,n)
end
- t[#t+1] = "]"
+ n = n + 1 ; t[n] = "]"
end
elseif kind == "string" then
- t[#t+1] = format("%q",value)
+ n = n + 1 ; t[n] = '"'
+ n = n + 1 ; t[n] = lpegmatch(escaper,value) or value
+ n = n + 1 ; t[n] = '"'
elseif kind == "number" then
- t[#t+1] = value
+ n = n + 1 ; t[n] = value
elseif kind == "boolean" then
- t[#t+1] = tostring(value)
+ n = n + 1 ; t[n] = tostring(value)
end
- return t
+ return t, n
end
function json.tostring(value)
-- todo optimize for non table
local kind = type(value)
if kind == "table" then
- return concat(tojson(value,{}),"")
+ if not escaper then
+ local escapes = {
+ ["\\"] = "\\u005C",
+ ["\""] = "\\u0022",
+ }
+ for i=0,0x20 do
+ escapes[utfchar(i)] = format("\\u%04X",i)
+ end
+ escaper = Cs( (
+ (R('\0\x20') + S('\"\\')) / escapes
+ + P(1)
+ )^1 )
+
+ end
+ return concat((tojson(value,{},0)))
elseif kind == "string" or kind == "number" then
- return value
+ return lpegmatch(escaper,value) or value
else
return tostring(value)
end
end
--- local tmp = [[ { "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]]
-
+-- local tmp = [[ { "t" : "foobar", "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]]
-- tmp = json.tolua(tmp)
-- inspect(tmp)
-- tmp = json.tostring(tmp)
@@ -155,7 +174,6 @@ end
-- inspect(tmp)
-- tmp = json.tostring(tmp)
-- inspect(tmp)
-
-- inspect(json.tostring(true))
function json.load(filename)
@@ -165,4 +183,11 @@ function json.load(filename)
end
end
+-- local s = [[\foo"bar"]]
+-- local j = json.tostring { s = s }
+-- local l = json.tolua(j)
+-- inspect(j)
+-- inspect(l)
+-- print(s==l.s)
+
return json
diff --git a/tex/context/base/mkiv/util-lib.lua b/tex/context/base/mkiv/util-lib.lua
index 714cfd4c7..fb65a566e 100644
--- a/tex/context/base/mkiv/util-lib.lua
+++ b/tex/context/base/mkiv/util-lib.lua
@@ -237,7 +237,7 @@ local function locate(required,version,trace,report,action)
report("stored library: %a",required)
end
end
- return library
+ return library or nil
end
do
@@ -352,7 +352,7 @@ We use the same lookup logic for ffi loading.
trackers.register("resolvers.ffilib", function(v) trace_ffilib = v end)
-- pushlibpath(pathpart(name))
- -- local message, library = pcall(savedffiload,nameonly(name))
+ -- local state, library = pcall(savedffiload,nameonly(name))
-- poplibpath()
local loaded = { }
@@ -361,11 +361,11 @@ We use the same lookup logic for ffi loading.
name = removesuffix(name)
local l = loaded[name]
if l == nil then
- local message, library = pcall(savedffiload,name)
- if type(message) == "userdata" then
- l = message
- elseif type(library) == "userdata" then
+ local state, library = pcall(savedffiload,name)
+ if type(library) == "userdata" then
l = library
+ elseif type(state) == "userdata" then
+ l = state
else
l = false
end
@@ -376,6 +376,20 @@ We use the same lookup logic for ffi loading.
return l
end
+ local function getlist(required)
+ local list = directives.value("system.librarynames" )
+ if type(list) == "table" then
+ list = list[required]
+ if type(list) == "table" then
+ if trace then
+ report("using lookup list for library %a: % | t",required,list)
+ end
+ return list
+ end
+ end
+ return { required }
+ end
+
function ffilib(name,version)
name = removesuffix(name)
local l = loaded[name]
@@ -384,23 +398,45 @@ We use the same lookup logic for ffi loading.
report_ffilib("reusing already loaded %a",name)
end
return l
- elseif version == "system" then
- return locateindeed(name)
+ end
+ local list = getlist(name)
+ if version == "system" then
+ for i=1,#list do
+ local library = locateindeed(list[i])
+ if type(library) == "userdata" then
+ return library
+ end
+ end
else
- return locate(name,version,trace_ffilib,report_ffilib,locateindeed)
+ for i=1,#list do
+ local library = locate(list[i],version,trace_ffilib,report_ffilib,locateindeed)
+ if type(library) == "userdata" then
+ return library
+ end
+ end
end
end
function ffi.load(name)
- local library = ffilib(name)
- if type(library) == "userdata" then
- return library
+ local list = getlist(name)
+ for i=1,#list do
+ local library = ffilib(list[i])
+ if type(library) == "userdata" then
+ return library
+ end
end
if trace_ffilib then
report_ffilib("trying to load %a using normal loader",name)
end
-- so here we don't store
- return savedffiload(name)
+ for i=1,#list do
+ local state, library = pcall(savedffiload,list[i])
+ if type(library) == "userdata" then
+ return library
+ elseif type(state) == "userdata" then
+ return library
+ end
+ end
end
end
diff --git a/tex/context/base/mkiv/util-lua.lua b/tex/context/base/mkiv/util-lua.lua
index b7de11936..1199301f4 100644
--- a/tex/context/base/mkiv/util-lua.lua
+++ b/tex/context/base/mkiv/util-lua.lua
@@ -88,6 +88,7 @@ function luautilities.loadedluacode(fullname,forcestrip,name,macros)
code()
else
report_lua("loading of file %a failed:\n\t%s",fullname,message or "no message")
+ code, message = loadfile(fullname)
end
if forcestrip and luautilities.stripcode then
if type(forcestrip) == "function" then
@@ -114,7 +115,7 @@ function luautilities.strippedloadstring(code,name,forcestrip) -- not executed
end
if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
register(name)
- return load(dump(code,true)), 0 -- not yet executes
+ return load(dump(code,true)), 0 -- not yet executed
else
return code, 0
end
@@ -198,12 +199,12 @@ function luautilities.checkmemory(previous,threshold,trace) -- threshold in MB
collectgarbage("collect")
local afterwards = collectgarbage("count")
if trace or tracememory then
- report_mem("previous %i MB, current %i MB, delta %i MB, threshold %i MB, afterwards %i MB",
+ report_mem("previous %r MB, current %r MB, delta %r MB, threshold %r MB, afterwards %r MB",
previous/1024,current/1024,delta/1024,threshold,afterwards)
end
return afterwards
elseif trace or tracememory then
- report_mem("previous %i MB, current %i MB, delta %i MB, threshold %i MB",
+ report_mem("previous %r MB, current %r MB, delta %r MB, threshold %r MB",
previous/1024,current/1024,delta/1024,threshold)
end
end
diff --git a/tex/context/base/mkiv/util-mrg.lua b/tex/context/base/mkiv/util-mrg.lua
index 690188ef8..bc835bf56 100644
--- a/tex/context/base/mkiv/util-mrg.lua
+++ b/tex/context/base/mkiv/util-mrg.lua
@@ -113,6 +113,7 @@ local pack = digit * space^1 * operator4 * optionalspacing +
optionalspaces * separator * optionalspaces
local lines = emptyline^2 / "\n"
local spaces = (space * space) / " "
+local spaces = (space * space * space * space) / " "
----- spaces = ((space+eol)^1 ) / " "
local compact = Cs ( (
diff --git a/tex/context/base/mkiv/util-prs.lua b/tex/context/base/mkiv/util-prs.lua
index 48d59a9f3..08401f222 100644
--- a/tex/context/base/mkiv/util-prs.lua
+++ b/tex/context/base/mkiv/util-prs.lua
@@ -31,6 +31,7 @@ utilities.parsers.hashes = hashes
local digit = R("09")
local space = P(' ')
local equal = P("=")
+local colon = P(":")
local comma = P(",")
local lbrace = P("{")
local rbrace = P("}")
@@ -72,11 +73,13 @@ lpegpatterns.nested = nestedbraces -- no capture
lpegpatterns.argument = argument -- argument after e.g. =
lpegpatterns.content = content -- rest after e.g =
-local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace) + C((nestedbraces + (1-comma))^0)
+local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace
+ + C((nestedbraces + (1-comma))^0)
local key = C((1-equal-comma)^1)
local pattern_a = (space+comma)^0 * (key * equal * value + key * C(""))
local pattern_c = (space+comma)^0 * (key * equal * value)
+local pattern_d = (space+comma)^0 * (key * (equal+colon) * value + key * C(""))
local key = C((1-space-equal-comma)^1)
local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + C("")))
@@ -92,10 +95,12 @@ 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
+local pattern_d_s = (pattern_d/set)^1
patterns.settings_to_hash_a = pattern_a_s
patterns.settings_to_hash_b = pattern_b_s
patterns.settings_to_hash_c = pattern_c_s
+patterns.settings_to_hash_d = pattern_d_s
function parsers.make_settings_to_hash_pattern(set,how)
if how == "strict" then
@@ -126,6 +131,18 @@ function parsers.settings_to_hash(str,existing)
end
end
+function parsers.settings_to_hash_colon_too(str)
+ if not str or str == "" then
+ return { }
+ elseif type(str) == "table" then
+ return str
+ else
+ hash = { }
+ lpegmatch(pattern_d_s,str)
+ return hash
+ end
+end
+
function parsers.settings_to_hash_tolerant(str,existing)
if not str or str == "" then
return { }
@@ -165,7 +182,7 @@ function parsers.settings_to_hash_strict(str,existing)
end
local separator = comma * space^0
-local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace)
+local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace
+ C((nestedbraces + (1-comma))^0)
local pattern = spaces * Ct(value*(separator*value)^0)
@@ -210,7 +227,7 @@ function parsers.settings_to_numbers(str)
return str
end
-local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace)
+local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace
+ C((nestedbraces + nestedbrackets + nestedparents + (1-comma))^0)
local pattern = spaces * Ct(value*(separator*value)^0)
@@ -242,7 +259,7 @@ function parsers.groupedsplitat(symbol,withaction)
if not pattern then
local symbols = S(symbol)
local separator = space^0 * symbols * space^0
- local value = P(lbrace * C((nobrace + nestedbraces)^0) * rbrace)
+ local value = lbrace * C((nobrace + nestedbraces)^0) * rbrace
+ C((nestedbraces + (1-(space^0*(symbols+P(-1)))))^0)
if withaction then
local withvalue = Carg(1) * value / function(f,s) return f(s) end
@@ -291,7 +308,9 @@ end
function parsers.hash_to_string(h,separator,yes,no,strict,omit)
if h then
- local t, tn, s = { }, 0, sortedkeys(h)
+ local t = { }
+ local tn = 0
+ local s = sortedkeys(h)
omit = omit and tohash(omit)
for i=1,#s do
local key = s[i]
@@ -357,7 +376,8 @@ end)
getmetatable(hashes.settings_to_set).__mode = "kv" -- could be an option (maybe sharing makes sense)
function parsers.simple_hash_to_string(h, separator)
- local t, tn = { }, 0
+ local t = { }
+ local tn = 0
for k, v in sortedhash(h) do
if v then
tn = tn + 1
@@ -398,7 +418,8 @@ local function repeater(n,str)
if n == 1 then
return unpack(s)
else
- local t, tn = { }, 0
+ local t = { }
+ local tn = 0
for i=1,n do
for j=1,#s do
tn = tn + 1
diff --git a/tex/context/base/mkiv/util-sac.lua b/tex/context/base/mkiv/util-sac.lua
index b509d9a9b..dc8ba72f1 100644
--- a/tex/context/base/mkiv/util-sac.lua
+++ b/tex/context/base/mkiv/util-sac.lua
@@ -10,15 +10,23 @@ if not modules then modules = { } end modules ['util-sac'] = {
-- with bytes)
local byte, sub = string.byte, string.sub
-local extract = bit32 and bit32.extract
+local tonumber = tonumber
utilities = utilities or { }
local streams = { }
utilities.streams = streams
function streams.open(filename,zerobased)
- local f = io.loaddata(filename)
- return { f, 1, #f, zerobased or false }
+ local f = filename and io.loaddata(filename)
+ if f then
+ return { f, 1, #f, zerobased or false }
+ end
+end
+
+function streams.openstring(f,zerobased)
+ if f then
+ return { f, 1, #f, zerobased or false }
+ end
end
function streams.close()
@@ -233,31 +241,31 @@ function streams.readinteger4le(f)
end
end
-function streams.readfixed4(f)
+function streams.readfixed2(f)
local i = f[2]
- local j = i + 3
+ local j = i + 1
f[2] = j + 1
- local a, b, c, d = byte(f[1],i,j)
+ local a, b = byte(f[1],i,j)
if a >= 0x80 then
- return (0x100 * a + b - 0x10000) + (0x100 * c + d)/0x10000
+ tonumber((a - 0x100) .. "." .. b)
else
- return (0x100 * a + b ) + (0x100 * c + d)/0x10000
+ tonumber((a ) .. "." .. b)
end
end
-function streams.readfixed2(f)
+function streams.readfixed4(f)
local i = f[2]
- local j = i + 1
+ local j = i + 3
f[2] = j + 1
- local a, b = byte(f[1],i,j)
+ local a, b, c, d = byte(f[1],i,j)
if a >= 0x80 then
- return (a - 0x100) + b/0x100
+ tonumber((0x100 * a + b - 0x10000) .. "." .. (0x100 * c + d))
else
- return (a ) + b/0x100
+ tonumber((0x100 * a + b ) .. "." .. (0x100 * c + d))
end
end
-if extract then
+if bit32 then
local extract = bit32.extract
local band = bit32.band
@@ -386,3 +394,80 @@ if sio and sio.readcardinal2 then
streams.readinteger = streams.readinteger1
end
+
+if sio and sio.readcardinaltable then
+
+ local readcardinaltable = sio.readcardinaltable
+ local readintegertable = sio.readintegertable
+
+ function utilities.streams.readcardinaltable(f,n,b)
+ local i = f[2]
+ local s = f[3]
+ local p = i + n * b
+ if p > s then
+ f[2] = s + 1
+ else
+ f[2] = p
+ end
+ return readcardinaltable(f[1],i,n,b)
+ end
+
+ function utilities.streams.readintegertable(f,n,b)
+ local i = f[2]
+ local s = f[3]
+ local p = i + n * b
+ if p > s then
+ f[2] = s + 1
+ else
+ f[2] = p
+ end
+ return readintegertable(f[1],i,n,b)
+ end
+
+else
+
+ local readcardinal1 = streams.readcardinal1
+ local readcardinal2 = streams.readcardinal2
+ local readcardinal3 = streams.readcardinal3
+ local readcardinal4 = streams.readcardinal4
+
+ function streams.readcardinaltable(f,n,b)
+ local i = f[2]
+ local s = f[3]
+ local p = i + n * b
+ if p > s then
+ f[2] = s + 1
+ else
+ f[2] = p
+ end
+ local t = { }
+ if b == 1 then for i=1,n do t[i] = readcardinal1(f[1],i) end
+ elseif b == 2 then for i=1,n do t[i] = readcardinal2(f[1],i) end
+ elseif b == 3 then for i=1,n do t[i] = readcardinal3(f[1],i) end
+ elseif b == 4 then for i=1,n do t[i] = readcardinal4(f[1],i) end end
+ return t
+ end
+
+ local readinteger1 = streams.readinteger1
+ local readinteger2 = streams.readinteger2
+ local readinteger3 = streams.readinteger3
+ local readinteger4 = streams.readinteger4
+
+ function streams.readintegertable(f,n,b)
+ local i = f[2]
+ local s = f[3]
+ local p = i + n * b
+ if p > s then
+ f[2] = s + 1
+ else
+ f[2] = p
+ end
+ local t = { }
+ if b == 1 then for i=1,n do t[i] = readinteger1(f[1],i) end
+ elseif b == 2 then for i=1,n do t[i] = readinteger2(f[1],i) end
+ elseif b == 3 then for i=1,n do t[i] = readinteger3(f[1],i) end
+ elseif b == 4 then for i=1,n do t[i] = readinteger4(f[1],i) end end
+ return t
+ end
+
+end
diff --git a/tex/context/base/mkiv/util-seq.lua b/tex/context/base/mkiv/util-seq.lua
index d302ff276..e7a503faf 100644
--- a/tex/context/base/mkiv/util-seq.lua
+++ b/tex/context/base/mkiv/util-seq.lua
@@ -17,26 +17,39 @@ use locals to refer to them when compiling the chain.</p>
-- todo: protect groups (as in tasks)
-local gsub, concat, gmatch = string.gsub, table.concat, string.gmatch
-local type, load = type, load
+local gsub, gmatch = string.gsub, string.gmatch
+local concat, sortedkeys = table.concat, table.sortedkeys
+local type, load, next, tostring = type, load, next, tostring
-utilities = utilities or { }
-local tables = utilities.tables
-local allocate = utilities.storage.allocate
+utilities = utilities or { }
+local tables = utilities.tables
+local allocate = utilities.storage.allocate
-local formatters = string.formatters
+local formatters = string.formatters
+local replacer = utilities.templates.replacer
-local sequencers = { }
-utilities.sequencers = sequencers
+local trace_used = false
+local trace_detail = false
+local report = logs.reporter("sequencer")
+local usedcount = 0
+local usednames = { }
-local functions = allocate()
-sequencers.functions = functions
+trackers.register("sequencers.used", function(v) trace_used = true end)
+trackers.register("sequencers.detail",function(v) trace_detail = true end)
+
+local sequencers = { }
+utilities.sequencers = sequencers
+
+local functions = allocate()
+sequencers.functions = functions
local removevalue = tables.removevalue
local replacevalue = tables.replacevalue
local insertaftervalue = tables.insertaftervalue
local insertbeforevalue = tables.insertbeforevalue
+local usedsequences = { }
+
local function validaction(action)
if type(action) == "string" then
local g = _G
@@ -63,9 +76,11 @@ function sequencers.new(t) -- was reset
gskip = { },
dirty = true,
runner = nil,
+ steps = 0,
}
if t then
s.arguments = t.arguments
+ s.templates = t.templates
s.returnvalues = t.returnvalues
s.results = t.results
local name = t.name
@@ -86,120 +101,142 @@ function sequencers.new(t) -- was reset
end
function sequencers.prependgroup(t,group,where)
- t = known[t]
- if t then
- local order = t.order
- removevalue(order,group)
- insertbeforevalue(order,where,group)
- t.list[group] = { }
- t.dirty = true
- t.runner = nil
+ if t and group then
+ t = known[t]
+ if t then
+ local order = t.order
+ removevalue(order,group)
+ insertbeforevalue(order,where,group)
+ t.list[group] = { }
+ t.dirty = true
+ t.runner = nil
+ end
end
end
function sequencers.appendgroup(t,group,where)
- t = known[t]
- if t then
- local order = t.order
- removevalue(order,group)
- insertaftervalue(order,where,group)
- t.list[group] = { }
- t.dirty = true
- t.runner = nil
+ if t and group then
+ t = known[t]
+ if t then
+ local order = t.order
+ removevalue(order,group)
+ insertaftervalue(order,where,group)
+ t.list[group] = { }
+ t.dirty = true
+ t.runner = nil
+ end
end
end
function sequencers.prependaction(t,group,action,where,kind,force)
- t = known[t]
- if t then
- local g = t.list[group]
- if g and (force or validaction(action)) then
- removevalue(g,action)
- insertbeforevalue(g,where,action)
- t.kind[action] = kind
- t.dirty = true
- t.runner = nil
+ if t and group and action then
+ t = known[t]
+ if t then
+ local g = t.list[group]
+ if g and (force or validaction(action)) then
+ removevalue(g,action)
+ insertbeforevalue(g,where,action)
+ t.kind[action] = kind
+ t.dirty = true
+ t.runner = nil
+ end
end
end
end
function sequencers.appendaction(t,group,action,where,kind,force)
- t = known[t]
- if t then
- local g = t.list[group]
- if g and (force or validaction(action)) then
- removevalue(g,action)
- insertaftervalue(g,where,action)
- t.kind[action] = kind
- t.dirty = true
- t.runner = nil
+ if t and group and action then
+ t = known[t]
+ if t then
+ local g = t.list[group]
+ if g and (force or validaction(action)) then
+ removevalue(g,action)
+ insertaftervalue(g,where,action)
+ t.kind[action] = kind
+ t.dirty = true
+ t.runner = nil
+ end
end
end
end
function sequencers.enableaction(t,action)
- t = known[t]
- if t then
- t.askip[action] = false
- t.dirty = true
- t.runner = nil
+ if t and action then
+ t = known[t]
+ if t then
+ t.askip[action] = false
+ t.dirty = true
+ t.runner = nil
+ end
end
end
function sequencers.disableaction(t,action)
- t = known[t]
- if t then
- t.askip[action] = true
- t.dirty = true
- t.runner = nil
+ if t and action then
+ t = known[t]
+ if t then
+ t.askip[action] = true
+ t.dirty = true
+ t.runner = nil
+ end
end
end
function sequencers.enablegroup(t,group)
- t = known[t]
- if t then
- t.gskip[action] = false
- t.dirty = true
- t.runner = nil
+ if t and group then
+ t = known[t]
+ if t then
+ t.gskip[group] = false
+ t.dirty = true
+ t.runner = nil
+ end
end
end
function sequencers.disablegroup(t,group)
- t = known[t]
- if t then
- t.gskip[action] = true
- t.dirty = true
- t.runner = nil
+ if t and group then
+ t = known[t]
+ if t then
+ t.gskip[group] = true
+ t.dirty = true
+ t.runner = nil
+ end
end
end
function sequencers.setkind(t,action,kind)
- t = known[t]
- if t then
- t.kind[action] = kind
- t.dirty = true
- t.runner = nil
+ if t and action then
+ t = known[t]
+ if t then
+ t.kind[action] = kind
+ t.dirty = true
+ t.runner = nil
+ end
end
end
function sequencers.removeaction(t,group,action,force)
- t = known[t]
- local g = t and t.list[group]
- if g and (force or validaction(action)) then
- removevalue(g,action)
- t.dirty = true
- t.runner = nil
+ if t and group and action then
+ t = known[t]
+ local g = t and t.list[group]
+ if g and (force or validaction(action)) then
+ removevalue(g,action)
+ t.dirty = true
+ t.runner = nil
+ end
end
end
function sequencers.replaceaction(t,group,oldaction,newaction,force)
- t = known[t]
- if t then
- local g = t.list[group]
- if g and (force or validaction(oldaction)) then
- replacevalue(g,oldaction,newaction)
- t.dirty = true
- t.runner = nil
+ if t and group and oldaction and newaction then
+ t = known[t]
+ if t then
+ local g = t.list[group]
+ if g and (force or validaction(oldaction)) then
+ replacevalue(g,oldaction,newaction)
+ t.dirty = true
+ t.runner = nil
+ end
end
end
end
@@ -209,9 +246,19 @@ local function localize(str)
end
local function construct(t)
- local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip
- local arguments, returnvalues, results = t.arguments or "...", t.returnvalues, t.results
- local variables, calls, n = { }, { }, 0
+ local list = t.list
+ local order = t.order
+ local kind = t.kind
+ local gskip = t.gskip
+ local askip = t.askip
+ local name = t.name or "?"
+ local arguments = t.arguments or "..."
+ local returnvalues = t.returnvalues
+ local results = t.results
+ local variables = { }
+ local calls = { }
+ local n = 0
+ usedcount = usedcount + 1
for i=1,#order do
local group = order[i]
if not gskip[group] then
@@ -219,6 +266,11 @@ local function construct(t)
for i=1,#actions do
local action = actions[i]
if not askip[action] then
+ if trace_used then
+ local action = tostring(action)
+ report("%02i: category %a, group %a, action %a",usedcount,name,group,action)
+ usednames[action] = true
+ end
local localized
if type(action) == "function" then
local name = localize(tostring(action))
@@ -242,6 +294,7 @@ local function construct(t)
end
end
t.dirty = false
+ t.steps = n
if n == 0 then
t.compiled = ""
else
@@ -253,30 +306,27 @@ local function construct(t)
t.compiled = formatters["%s\nreturn function(%s)\n%s\nend"](variables,arguments,calls)
end
end
--- print(t.compiled)
return t.compiled -- also stored so that we can trace
end
sequencers.tostring = construct
sequencers.localize = localize
-compile = function(t,compiler,n) -- already referred to in sequencers.new
+compile = function(t,compiler,...) -- already referred to in sequencers.new
local compiled
if not t or type(t) == "string" then
- -- weird ... t.compiled = t .. so
return false
end
if compiler then
- compiled = compiler(t,n)
+ compiled = compiler(t,...)
t.compiled = compiled
else
- compiled = construct(t,n)
+ compiled = construct(t,...)
end
local runner
if compiled == "" then
runner = false
else
--- inspect(compiled)
runner = compiled and load(compiled)() -- we can use loadstripped here
end
t.runner = runner
@@ -285,52 +335,45 @@ end
sequencers.compile = compile
--- we used to deal with tail as well but now that the lists are always
--- double linked and the kernel function no longer expect tail as
--- argument we stick to head and done (done can probably also go
--- as luatex deals with return values efficiently now .. in the
--- past there was some copying involved, but no longer)
-
--- todo: use sequencer (can have arguments and returnvalues etc now)
-
-local template_yes_state = [[
-%s
-return function(head%s)
- local ok, done = false, false
-%s
- return head, done
-end]]
-
-local template_yes_nostate = [[
-%s
-return function(head%s)
-%s
- return head, true
-end]]
-
-local template_nop = [[
-return function()
- return false, false
-end]]
-
-function sequencers.nodeprocessor(t,nofarguments) -- todo: handle 'kind' in plug into tostring
- local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip
- local nostate = t.nostate
- local vars, calls, args, n = { }, { }, nil, 0
- if nofarguments == 0 then
- args = ""
- elseif nofarguments == 1 then
- args = ",one"
- elseif nofarguments == 2 then
- args = ",one,two"
- elseif nofarguments == 3 then -- from here on probably slower than ...
- args = ",one,two,three"
- elseif nofarguments == 4 then
- args = ",one,two,three,four"
- elseif nofarguments == 5 then
- args = ",one,two,three,four,five"
- else
- args = ",..."
+function sequencers.nodeprocessor(t,nofarguments)
+ --
+ local templates = nofarguments
+ --
+ if type(templates) ~= "table" then
+ return ""
+ end
+ --
+ local replacers = { }
+ for k, v in next, templates do
+ replacers[k] = replacer(v)
+ end
+ --
+ local construct = replacers.process
+ local step = replacers.step
+ if not construct or not step then
+ return ""
+ end
+ --
+ local calls = { }
+ local aliases = { }
+ local ncalls = 0
+ local naliases = 0
+ local f_alias = formatters["local %s = %s"]
+ --
+ local list = t.list
+ local order = t.order
+ local kind = t.kind
+ local gskip = t.gskip
+ local askip = t.askip
+ local name = t.name or "?"
+ local steps = 0
+ usedcount = usedcount + 1
+ --
+ if trace_detail then
+ naliases = naliases + 1
+ aliases[naliases] = formatters["local report = logs.reporter('sequencer',%q)"](name)
+ ncalls = ncalls + 1
+ calls[ncalls] = [[report("start")]]
end
for i=1,#order do
local group = order[i]
@@ -339,28 +382,47 @@ function sequencers.nodeprocessor(t,nofarguments) -- todo: handle 'kind' in plug
for i=1,#actions do
local action = actions[i]
if not askip[action] then
- local localized = localize(action)
- n = n + 1
- vars[n] = formatters["local %s = %s"](localized,action)
- -- only difference with tostring is kind and rets (why no return)
- if nostate then
- if kind[action] == "nohead" then
- calls[n] = formatters[" %s(head%s)"](localized,args)
- else
- calls[n] = formatters[" head = %s(head%s)"](localized,args)
- end
- else
- if kind[action] == "nohead" then
- calls[n] = formatters[" ok = %s(head%s) if ok then done = true end"](localized,args)
- else
- calls[n] = formatters[" head, ok = %s(head%s) if ok then done = true end"](localized,args)
- end
+ steps = steps + 1
+ if trace_used or trace_detail then
+ local action = tostring(action)
+ report("%02i: category %a, group %a, action %a",usedcount,name,group,action)
+ usednames[action] = true
end
+ if trace_detail then
+ ncalls = ncalls + 1
+ calls[ncalls] = formatters[ [[report(" step %a, action %a")]] ](steps,tostring(action))
+ end
+ local localized = localize(action)
+ local onestep = replacers[kind[action]] or step
+ naliases = naliases + 1
+ ncalls = ncalls + 1
+ aliases[naliases] = f_alias(localized,action)
+ calls [ncalls] = onestep { action = localized }
end
end
end
end
- local processor = #calls > 0 and formatters[nostate and template_yes_nostate or template_yes_state](concat(vars,"\n"),args,concat(calls,"\n")) or template_nop
+ t.steps = steps
+ local processor
+ if steps == 0 then
+ processor = templates.default or construct { }
+ else
+ if trace_detail then
+ ncalls = ncalls + 1
+ calls[ncalls] = [[report("stop")]]
+ end
+ processor = construct {
+ localize = concat(aliases,"\n"),
+ actions = concat(calls,"\n"),
+ }
+ end
+ -- processor = "print('running : " .. (t.name or "?") .. "')\n" .. processor
-- print(processor)
return processor
end
+
+statistics.register("used sequences",function()
+ if next(usednames) then
+ return concat(sortedkeys(usednames)," ")
+ end
+end)
diff --git a/tex/context/base/mkiv/util-sha.lua b/tex/context/base/mkiv/util-sha.lua
index 3e786a834..d84e46975 100644
--- a/tex/context/base/mkiv/util-sha.lua
+++ b/tex/context/base/mkiv/util-sha.lua
@@ -8,6 +8,13 @@ if not modules then modules = { } end modules ['util-sha'] = {
comment3 = "due to bit operators this code only works in lua(tex) 5.3",
}
+if sha2 then
+ if utilities then
+ utilities.sha2 = sha2
+ end
+ return sha2
+end
+
-- This doesn't work in luajittex ... maybe some day it will have bit operators too.
-- I'm not really in the mood for making this module aware (by compiling the
-- function depending on the engine that I use but I probably won't use luajittex in
@@ -277,10 +284,10 @@ digest[224] = digest[256]
digest[384] = digest[512]
local finalize = {
- [224] = function(hash,tohex) return tohex(packstring(">I4I4I4I4I4I4I4", unpack(hash))) end, -- # 56
- [256] = function(hash,tohex) return tohex(packstring(">I4I4I4I4I4I4I4I4",unpack(hash))) end, -- # 64
- [384] = function(hash,tohex) return tohex(packstring(">I8I8I8I8I8I8", unpack(hash))) end, -- # 96
- [512] = function(hash,tohex) return tohex(packstring(">I8I8I8I8I8I8I8I8",unpack(hash))) end, -- # 128
+ [224] = function(hash,tohex) local s = packstring(">I4I4I4I4I4I4I4", unpack(hash)) return tohex and tohex(s) or s end, -- # 56
+ [256] = function(hash,tohex) local s = packstring(">I4I4I4I4I4I4I4I4",unpack(hash)) return tohex and tohex(s) or s end, -- # 64
+ [384] = function(hash,tohex) local s = packstring(">I8I8I8I8I8I8", unpack(hash)) return tohex and tohex(s) or s end, -- # 96
+ [512] = function(hash,tohex) local s = packstring(">I8I8I8I8I8I8I8I8",unpack(hash)) return tohex and tohex(s) or s end, -- # 128
}
local hash = { }
@@ -293,14 +300,18 @@ local function hashed(str,method,tohex)
end
local sha2 = {
- hash224 = function(str) return hashed(str,224,tohex) end,
- hash256 = function(str) return hashed(str,256,tohex) end,
- hash384 = function(str) return hashed(str,384,tohex) end,
- hash512 = function(str) return hashed(str,512,tohex) end,
- HASH224 = function(str) return hashed(str,224,toHEX) end,
- HASH256 = function(str) return hashed(str,256,toHEX) end,
- HASH384 = function(str) return hashed(str,384,toHEX) end,
- HASH512 = function(str) return hashed(str,512,toHEX) end,
+ digest224 = function(str) return hashed(str,224) end,
+ digest256 = function(str) return hashed(str,256) end,
+ digest384 = function(str) return hashed(str,384) end,
+ digest512 = function(str) return hashed(str,512) end,
+ hash224 = function(str) return hashed(str,224,tohex) end,
+ hash256 = function(str) return hashed(str,256,tohex) end,
+ hash384 = function(str) return hashed(str,384,tohex) end,
+ hash512 = function(str) return hashed(str,512,tohex) end,
+ HASH224 = function(str) return hashed(str,224,toHEX) end,
+ HASH256 = function(str) return hashed(str,256,toHEX) end,
+ HASH384 = function(str) return hashed(str,384,toHEX) end,
+ HASH512 = function(str) return hashed(str,512,toHEX) end,
}
-- local setmetatableindex = table.setmetatableindex
diff --git a/tex/context/base/mkiv/util-soc-imp-copas.lua b/tex/context/base/mkiv/util-soc-imp-copas.lua
new file mode 100644
index 000000000..3e66e5888
--- /dev/null
+++ b/tex/context/base/mkiv/util-soc-imp-copas.lua
@@ -0,0 +1,931 @@
+-- original file : copas.lua
+-- for more into : see util-soc.lua
+
+local socket = socket or require("socket")
+local ssl = ssl or nil -- only loaded upon demand
+
+local WATCH_DOG_TIMEOUT = 120
+local UDP_DATAGRAM_MAX = 8192
+
+local type, next, pcall, getmetatable, tostring = type, next, pcall, getmetatable, tostring
+local min, max, random = math.min, math.max, math.random
+local find = string.find
+local insert, remove = table.insert, table.remove
+
+local gettime = socket.gettime
+local selectsocket = socket.select
+
+local createcoroutine = coroutine.create
+local resumecoroutine = coroutine.resume
+local yieldcoroutine = coroutine.yield
+local runningcoroutine = coroutine.running
+
+-- Redefines LuaSocket functions with coroutine safe versions (this allows the use
+-- of socket.http from within copas).
+
+-- Meta information is public even if beginning with an "_"
+
+local function report(fmt,first,...)
+ if logs then
+ report = logs and logs.reporter("copas")
+ report(fmt,first,...)
+ elseif fmt then
+ fmt = "copas: " .. fmt
+ if first then
+ print(format(fmt,first,...))
+ else
+ print(fmt)
+ end
+ end
+end
+
+local copas = {
+
+ _COPYRIGHT = "Copyright (C) 2005-2016 Kepler Project",
+ _DESCRIPTION = "Coroutine Oriented Portable Asynchronous Services",
+ _VERSION = "Copas 2.0.1",
+
+ autoclose = true,
+ running = false,
+
+ report = report,
+
+}
+
+local function statushandler(status, ...)
+ if status then
+ return ...
+ end
+ local err = (...)
+ if type(err) == "table" then
+ err = err[1]
+ end
+ report("error: %s",tostring(err))
+ return nil, err
+end
+
+function socket.protect(func)
+ return function(...)
+ return statushandler(pcall(func,...))
+ end
+end
+
+function socket.newtry(finalizer)
+ return function (...)
+ local status = (...)
+ if not status then
+ local detail = select(2,...)
+ pcall(finalizer,detail)
+ report("error: %s",tostring(detail))
+ return
+ end
+ return ...
+ end
+end
+
+-- Simple set implementation based on LuaSocket's tinyirc.lua example
+-- adds a FIFO queue for each value in the set
+
+local function newset()
+ local reverse = { }
+ local set = { }
+ local queue = { }
+ setmetatable(set, {
+ __index = {
+ insert =
+ function(set, value)
+ if not reverse[value] then
+ local n = #set +1
+ set[n] = value
+ reverse[value] = n
+ end
+ end,
+ remove =
+ function(set, value)
+ local index = reverse[value]
+ if index then
+ reverse[value] = nil
+ local n = #set
+ local top = set[n]
+ set[n] = nil
+ if top ~= value then
+ reverse[top] = index
+ set[index] = top
+ end
+ end
+ end,
+ push =
+ function (set, key, itm)
+ local entry = queue[key]
+ if entry == nil then -- hm can it be false then?
+ queue[key] = { itm }
+ else
+ entry[#entry + 1] = itm
+ end
+ end,
+ pop =
+ function (set, key)
+ local top = queue[key]
+ if top ~= nil then
+ local ret = remove(top,1)
+ if top[1] == nil then
+ queue[key] = nil
+ end
+ return ret
+ end
+ end
+ }
+ } )
+ return set
+end
+
+local _sleeping = {
+ times = { }, -- list with wake-up times
+ cos = { }, -- list with coroutines, index matches the 'times' list
+ lethargy = { }, -- list of coroutines sleeping without a wakeup time
+
+ insert =
+ function()
+ end,
+ remove =
+ function()
+ end,
+ push =
+ function(self, sleeptime, co)
+ if not co then
+ return
+ end
+ if sleeptime < 0 then
+ --sleep until explicit wakeup through copas.wakeup
+ self.lethargy[co] = true
+ return
+ else
+ sleeptime = gettime() + sleeptime
+ end
+ local t = self.times
+ local c = self.cos
+ local i = 1
+ local n = #t
+ while i <= n and t[i] <= sleeptime do
+ i = i + 1
+ end
+ insert(t,i,sleeptime)
+ insert(c,i,co)
+ end,
+ getnext =
+ -- returns delay until next sleep expires, or nil if there is none
+ function(self)
+ local t = self.times
+ local delay = t[1] and t[1] - gettime() or nil
+ return delay and max(delay, 0) or nil
+ end,
+ pop =
+ -- find the thread that should wake up to the time
+ function(self, time)
+ local t = self.times
+ local c = self.cos
+ if #t == 0 or time < t[1] then
+ return
+ end
+ local co = c[1]
+ remove(t,1)
+ remove(c,1)
+ return co
+ end,
+ wakeup =
+ function(self, co)
+ local let = self.lethargy
+ if let[co] then
+ self:push(0, co)
+ let[co] = nil
+ else
+ local c = self.cos
+ local t = self.times
+ for i=1,#c do
+ if c[i] == co then
+ remove(c,i)
+ remove(t,i)
+ self:push(0, co)
+ return
+ end
+ end
+ end
+ end
+}
+
+local _servers = newset() -- servers being handled
+local _reading = newset() -- sockets currently being read
+local _writing = newset() -- sockets currently being written
+
+local _reading_log = { }
+local _writing_log = { }
+
+local _is_timeout = { -- set of errors indicating a timeout
+ timeout = true, -- default LuaSocket timeout
+ wantread = true, -- LuaSec specific timeout
+ wantwrite = true, -- LuaSec specific timeout
+}
+
+-- Coroutine based socket I/O functions.
+
+local function isTCP(socket)
+ return not find(tostring(socket),"^udp")
+end
+
+-- Reads a pattern from a client and yields to the reading set on timeouts UDP: a
+-- UDP socket expects a second argument to be a number, so it MUST be provided as
+-- the 'pattern' below defaults to a string. Will throw a 'bad argument' error if
+-- omitted.
+
+local function copasreceive(client, pattern, part)
+ if not pattern or pattern == "" then
+ pattern = "*l"
+ end
+ local current_log = _reading_log
+ local s, err
+ repeat
+ s, err, part = client:receive(pattern, part)
+ if s or (not _is_timeout[err]) then
+ current_log[client] = nil
+ return s, err, part
+ end
+ if err == "wantwrite" then
+ current_log = _writing_log
+ current_log[client] = gettime()
+ yieldcoroutine(client, _writing)
+ else
+ current_log = _reading_log
+ current_log[client] = gettime()
+ yieldcoroutine(client, _reading)
+ end
+ until false
+end
+
+-- Receives data from a client over UDP. Not available for TCP. (this is a copy of
+-- receive() method, adapted for receivefrom() use).
+
+local function copasreceivefrom(client, size)
+ local s, err, port
+ if not size or size == 0 then
+ size = UDP_DATAGRAM_MAX
+ end
+ repeat
+ -- upon success err holds ip address
+ s, err, port = client:receivefrom(size)
+ if s or err ~= "timeout" then
+ _reading_log[client] = nil
+ return s, err, port
+ end
+ _reading_log[client] = gettime()
+ yieldcoroutine(client, _reading)
+ until false
+end
+
+-- Same as above but with special treatment when reading chunks, unblocks on any
+-- data received.
+
+local function copasreceivepartial(client, pattern, part)
+ if not pattern or pattern == "" then
+ pattern = "*l"
+ end
+ local logger = _reading_log
+ local queue = _reading
+ local s, err
+ repeat
+ s, err, part = client:receive(pattern, part)
+ if s or (type(pattern) == "number" and part ~= "" and part) or not _is_timeout[err] then
+ logger[client] = nil
+ return s, err, part
+ end
+ if err == "wantwrite" then
+ logger = _writing_log
+ queue = _writing
+ else
+ logger = _reading_log
+ queue = _reading
+ end
+ logger[client] = gettime()
+ yieldcoroutine(client, queue)
+ until false
+end
+
+-- Sends data to a client. The operation is buffered and yields to the writing set
+-- on timeouts Note: from and to parameters will be ignored by/for UDP sockets
+
+local function copassend(client, data, from, to)
+ if not from then
+ from = 1
+ end
+ local lastIndex = from - 1
+ local logger = _writing_log
+ local queue = _writing
+ local s, err
+ repeat
+ s, err, lastIndex = client:send(data, lastIndex + 1, to)
+ -- Adds extra coroutine swap and garantees that high throughput doesn't take
+ -- other threads to starvation.
+ if random(100) > 90 then
+ logger[client] = gettime()
+ yieldcoroutine(client, queue)
+ end
+ if s or not _is_timeout[err] then
+ logger[client] = nil
+ return s, err,lastIndex
+ end
+ if err == "wantread" then
+ logger = _reading_log
+ queue = _reading
+ else
+ logger = _writing_log
+ queue = _writing
+ end
+ logger[client] = gettime()
+ yieldcoroutine(client, queue)
+ until false
+end
+
+-- Sends data to a client over UDP. Not available for TCP. (this is a copy of send()
+-- method, adapted for sendto() use).
+
+local function copassendto(client, data, ip, port)
+ repeat
+ local s, err = client:sendto(data, ip, port)
+ -- Adds extra coroutine swap and garantees that high throughput doesn't
+ -- take other threads to starvation.
+ if random(100) > 90 then
+ _writing_log[client] = gettime()
+ yieldcoroutine(client, _writing)
+ end
+ if s or err ~= "timeout" then
+ _writing_log[client] = nil
+ return s, err
+ end
+ _writing_log[client] = gettime()
+ yieldcoroutine(client, _writing)
+ until false
+end
+
+-- Waits until connection is completed.
+
+local function copasconnect(skt, host, port)
+ skt:settimeout(0)
+ local ret, err, tried_more_than_once
+ repeat
+ ret, err = skt:connect (host, port)
+ -- A non-blocking connect on Windows results in error "Operation already in
+ -- progress" to indicate that it is completing the request async. So
+ -- essentially it is the same as "timeout".
+ if ret or (err ~= "timeout" and err ~= "Operation already in progress") then
+ -- Once the async connect completes, Windows returns the error "already
+ -- connected" to indicate it is done, so that error should be ignored.
+ -- Except when it is the first call to connect, then it was already
+ -- connected to something else and the error should be returned.
+ if not ret and err == "already connected" and tried_more_than_once then
+ ret = 1
+ err = nil
+ end
+ _writing_log[skt] = nil
+ return ret, err
+ end
+ tried_more_than_once = tried_more_than_once or true
+ _writing_log[skt] = gettime()
+ yieldcoroutine(skt, _writing)
+ until false
+end
+
+-- Peforms an (async) ssl handshake on a connected TCP client socket. Replacec all
+-- previous socket references, with the returned new ssl wrapped socket Throws error
+-- and does not return nil+error, as that might silently fail in code like this.
+
+local function copasdohandshake(skt, sslt) -- extra ssl parameters
+ if not ssl then
+ ssl = require("ssl")
+ end
+ if not ssl then
+ report("error: no ssl library")
+ return
+ end
+ local nskt, err = ssl.wrap(skt, sslt)
+ if not nskt then
+ report("error: %s",tostring(err))
+ return
+ end
+ nskt:settimeout(0)
+ local queue
+ repeat
+ local success, err = nskt:dohandshake()
+ if success then
+ return nskt
+ elseif err == "wantwrite" then
+ queue = _writing
+ elseif err == "wantread" then
+ queue = _reading
+ else
+ report("error: %s",tostring(err))
+ return
+ end
+ yieldcoroutine(nskt, queue)
+ until false
+end
+
+-- Flushes a client write buffer.
+
+local function copasflush(client)
+end
+
+-- Public.
+
+copas.connect = copassconnect
+copas.send = copassend
+copas.sendto = copassendto
+copas.receive = copasreceive
+copas.receivefrom = copasreceivefrom
+copas.copasreceivepartial = copasreceivepartial
+copas.copasreceivePartial = copasreceivepartial
+copas.dohandshake = copasdohandshake
+copas.flush = copasflush
+
+-- Wraps a TCP socket to use Copas methods (send, receive, flush and settimeout).
+
+local function _skt_mt_tostring(self)
+ return tostring(self.socket) .. " (copas wrapped)"
+end
+
+local _skt_mt_tcp_index = {
+ send =
+ function(self, data, from, to)
+ return copassend (self.socket, data, from, to)
+ end,
+ receive =
+ function (self, pattern, prefix)
+ if self.timeout == 0 then
+ return copasreceivePartial(self.socket, pattern, prefix)
+ else
+ return copasreceive(self.socket, pattern, prefix)
+ end
+ end,
+
+ flush =
+ function (self)
+ return copasflush(self.socket)
+ end,
+
+ settimeout =
+ function (self, time)
+ self.timeout = time
+ return true
+ end,
+ -- TODO: socket.connect is a shortcut, and must be provided with an alternative
+ -- if ssl parameters are available, it will also include a handshake
+ connect =
+ function(self, ...)
+ local res, err = copasconnect(self.socket, ...)
+ if res and self.ssl_params then
+ res, err = self:dohandshake()
+ end
+ return res, err
+ end,
+ close =
+ function(self, ...)
+ return self.socket:close(...)
+ end,
+ -- TODO: socket.bind is a shortcut, and must be provided with an alternative
+ bind =
+ function(self, ...)
+ return self.socket:bind(...)
+ end,
+ -- TODO: is this DNS related? hence blocking?
+ getsockname =
+ function(self, ...)
+ return self.socket:getsockname(...)
+ end,
+ getstats =
+ function(self, ...)
+ return self.socket:getstats(...)
+ end,
+ setstats =
+ function(self, ...)
+ return self.socket:setstats(...)
+ end,
+ listen =
+ function(self, ...)
+ return self.socket:listen(...)
+ end,
+ accept =
+ function(self, ...)
+ return self.socket:accept(...)
+ end,
+ setoption =
+ function(self, ...)
+ return self.socket:setoption(...)
+ end,
+ -- TODO: is this DNS related? hence blocking?
+ getpeername =
+ function(self, ...)
+ return self.socket:getpeername(...)
+ end,
+ shutdown =
+ function(self, ...)
+ return self.socket:shutdown(...)
+ end,
+ dohandshake =
+ function(self, sslt)
+ self.ssl_params = sslt or self.ssl_params
+ local nskt, err = copasdohandshake(self.socket, self.ssl_params)
+ if not nskt then
+ return nskt, err
+ end
+ self.socket = nskt
+ return self
+ end,
+}
+
+local _skt_mt_tcp = {
+ __tostring = _skt_mt_tostring,
+ __index = _skt_mt_tcp_index,
+}
+
+-- wraps a UDP socket, copy of TCP one adapted for UDP.
+
+local _skt_mt_udp_index = {
+ -- UDP sending is non-blocking, but we provide starvation prevention, so replace
+ -- anyway.
+ sendto =
+ function (self, ...)
+ return copassendto(self.socket,...)
+ end,
+ receive =
+ function (self, size)
+ return copasreceive(self.socket, size or UDP_DATAGRAM_MAX)
+ end,
+ receivefrom =
+ function (self, size)
+ return copasreceivefrom(self.socket, size or UDP_DATAGRAM_MAX)
+ end,
+ -- TODO: is this DNS related? hence blocking?
+ setpeername =
+ function(self, ...)
+ return self.socket:getpeername(...)
+ end,
+ setsockname =
+ function(self, ...)
+ return self.socket:setsockname(...)
+ end,
+ -- do not close client, as it is also the server for udp.
+ close =
+ function(self, ...)
+ return true
+ end
+}
+
+local _skt_mt_udp = {
+ __tostring = _skt_mt_tostring,
+ __index = _skt_mt_udp_index,
+}
+
+for k, v in next, _skt_mt_tcp_index do
+ if not _skt_mt_udp_index[k] then
+ _skt_mt_udp_index[k] = v
+ end
+end
+
+-- Wraps a LuaSocket socket object in an async Copas based socket object.
+
+-- @param skt the socket to wrap
+-- @sslt (optional) Table with ssl parameters, use an empty table to use ssl with defaults
+-- @return wrapped socket object
+
+local function wrap(skt, sslt)
+ if getmetatable(skt) == _skt_mt_tcp or getmetatable(skt) == _skt_mt_udp then
+ return skt -- already wrapped
+ end
+ skt:settimeout(0)
+ if isTCP(skt) then
+ return setmetatable ({ socket = skt, ssl_params = sslt }, _skt_mt_tcp)
+ else
+ return setmetatable ({ socket = skt }, _skt_mt_udp)
+ end
+end
+
+copas.wrap = wrap
+
+-- Wraps a handler in a function that deals with wrapping the socket and doing
+-- the optional ssl handshake.
+
+function copas.handler(handler, sslparams)
+ return function (skt,...)
+ skt = wrap(skt)
+ if sslparams then
+ skt:dohandshake(sslparams)
+ end
+ return handler(skt,...)
+ end
+end
+
+-- Error handling (a handler per coroutine).
+
+local _errhandlers = { }
+
+function copas.setErrorHandler(err)
+ local co = runningcoroutine()
+ if co then
+ _errhandlers[co] = err
+ end
+end
+
+local function _deferror (msg, co, skt)
+ report("%s (%s) (%s)", msg, tostring(co), tostring(skt))
+end
+
+-- Thread handling
+
+local function _doTick (co, skt, ...)
+ if not co then
+ return
+ end
+
+ local ok, res, new_q = resumecoroutine(co, skt, ...)
+
+ if ok and res and new_q then
+ new_q:insert(res)
+ new_q:push(res, co)
+ else
+ if not ok then
+ pcall(_errhandlers[co] or _deferror, res, co, skt)
+ end
+ -- Do not auto-close UDP sockets, as the handler socket is also the server socket.
+ if skt and copas.autoclose and isTCP(skt) then
+ skt:close()
+ end
+ _errhandlers[co] = nil
+ end
+end
+
+-- Accepts a connection on socket input.
+
+local function _accept(input, handler)
+ local client = input:accept()
+ if client then
+ client:settimeout(0)
+ local co = createcoroutine(handler)
+ _doTick (co, client)
+ -- _reading:insert(client)
+ end
+ return client
+end
+
+-- Handle threads on a queue.
+
+local function _tickRead(skt)
+ _doTick(_reading:pop(skt), skt)
+end
+
+local function _tickWrite(skt)
+ _doTick(_writing:pop(skt), skt)
+end
+
+-- Adds a server/handler pair to Copas dispatcher.
+
+local function addTCPserver(server, handler, timeout)
+ server:settimeout(timeout or 0)
+ _servers[server] = handler
+ _reading:insert(server)
+end
+
+local function addUDPserver(server, handler, timeout)
+ server:settimeout(timeout or 0)
+ local co = createcoroutine(handler)
+ _reading:insert(server)
+ _doTick(co, server)
+end
+
+function copas.addserver(server, handler, timeout)
+ if isTCP(server) then
+ addTCPserver(server, handler, timeout)
+ else
+ addUDPserver(server, handler, timeout)
+ end
+end
+
+function copas.removeserver(server, keep_open)
+ local s = server
+ local mt = getmetatable(server)
+ if mt == _skt_mt_tcp or mt == _skt_mt_udp then
+ s = server.socket
+ end
+ _servers[s] = nil
+ _reading:remove(s)
+ if keep_open then
+ return true
+ end
+ return server:close()
+end
+
+-- Adds an new coroutine thread to Copas dispatcher. Create a coroutine that skips
+-- the first argument, which is always the socket passed by the scheduler, but `nil`
+-- in case of a task/thread
+
+function copas.addthread(handler, ...)
+ local thread = createcoroutine(function(_, ...) return handler(...) end)
+ _doTick(thread, nil, ...)
+ return thread
+end
+
+-- tasks registering
+
+local _tasks = { }
+
+-- Lets tasks call the default _tick().
+
+local function addtaskRead(task)
+ task.def_tick = _tickRead
+ _tasks[task] = true
+end
+
+-- Lets tasks call the default _tick().
+
+local function addtaskWrite(task)
+ task.def_tick = _tickWrite
+ _tasks[task] = true
+end
+
+local function tasks()
+ return next, _tasks
+end
+
+-- A task to check ready to read events.
+
+local _readable_t = {
+ events =
+ function(self)
+ local i = 0
+ return function ()
+ i = i + 1
+ return self._evs[i]
+ end
+ end,
+ tick =
+ function(self, input)
+ local handler = _servers[input]
+ if handler then
+ input = _accept(input, handler)
+ else
+ _reading:remove(input)
+ self.def_tick(input)
+ end
+ end
+}
+
+addtaskRead(_readable_t)
+
+-- A task to check ready to write events.
+
+local _writable_t = {
+ events =
+ function(self)
+ local i = 0
+ return function()
+ i = i + 1
+ return self._evs[i]
+ end
+ end,
+ tick =
+ function(self, output)
+ _writing:remove(output)
+ self.def_tick(output)
+ end
+}
+
+addtaskWrite(_writable_t)
+
+--sleeping threads task
+
+local _sleeping_t = {
+ tick = function(self, time, ...)
+ _doTick(_sleeping:pop(time), ...)
+ end
+}
+
+-- yields the current coroutine and wakes it after 'sleeptime' seconds.
+-- If sleeptime<0 then it sleeps until explicitly woken up using 'wakeup'
+function copas.sleep(sleeptime)
+ yieldcoroutine((sleeptime or 0), _sleeping)
+end
+
+-- Wakes up a sleeping coroutine 'co'.
+
+function copas.wakeup(co)
+ _sleeping:wakeup(co)
+end
+
+-- Checks for reads and writes on sockets
+
+local last_cleansing = 0
+
+local function _select(timeout)
+
+ local now = gettime()
+
+ local r_evs, w_evs, err = selectsocket(_reading, _writing, timeout)
+
+ _readable_t._evs = r_evs
+ _writable_t._evs = w_evs
+
+ if (last_cleansing - now) > WATCH_DOG_TIMEOUT then
+
+ last_cleansing = now
+
+ -- Check all sockets selected for reading, and check how long they have been
+ -- waiting for data already, without select returning them as readable.
+
+ for skt, time in next, _reading_log do
+
+ if not r_evs[skt] and (time - now) > WATCH_DOG_TIMEOUT then
+
+ -- This one timedout while waiting to become readable, so move it in
+ -- the readable list and try and read anyway, despite not having
+ -- been returned by select.
+
+ local n = #r_evs + 1
+ _reading_log[skt] = nil
+ r_evs[n] = skt
+ r_evs[skt] = n
+ end
+ end
+
+ -- Do the same for writing.
+
+ for skt, time in next, _writing_log do
+ if not w_evs[skt] and (time - now) > WATCH_DOG_TIMEOUT then
+ local n = #w_evs + 1
+ _writing_log[skt] = nil
+ w_evs[n] = skt
+ w_evs[skt] = n
+ end
+ end
+
+ end
+
+ if err == "timeout" and #r_evs + #w_evs > 0 then
+ return nil
+ else
+ return err
+ end
+
+end
+
+-- Check whether there is something to do. It returns false if there are no sockets
+-- for read/write nor tasks scheduled (which means Copas is in an empty spin).
+
+local function copasfinished()
+ return not (next(_reading) or next(_writing) or _sleeping:getnext())
+end
+
+-- Dispatcher loop step. It listens to client requests and handles them and returns
+-- false if no data was handled (timeout), or true if there was data handled (or nil
+-- + error message).
+
+local function copasstep(timeout)
+ _sleeping_t:tick(gettime())
+
+ local nextwait = _sleeping:getnext()
+ if nextwait then
+ timeout = timeout and min(nextwait,timeout) or nextwait
+ elseif copasfinished() then
+ return false
+ end
+
+ local err = _select(timeout)
+ if err then
+ if err == "timeout" then
+ return false
+ end
+ return nil, err
+ end
+
+ for task in tasks() do
+ for event in task:events() do
+ task:tick(event)
+ end
+ end
+ return true
+end
+
+copas.finished = copasfinished
+copas.step = copasstep
+
+-- Dispatcher endless loop. It listens to client requests and handles them forever.
+
+function copas.loop(timeout)
+ copas.running = true
+ while not copasfinished() do
+ copasstep(timeout)
+ end
+ copas.running = false
+end
+
+-- _G.copas = copas
+
+package.loaded["copas"] = copas
+
+return copas
diff --git a/tex/context/base/mkiv/util-soc-imp-ftp.lua b/tex/context/base/mkiv/util-soc-imp-ftp.lua
new file mode 100644
index 000000000..124c8d4ee
--- /dev/null
+++ b/tex/context/base/mkiv/util-soc-imp-ftp.lua
@@ -0,0 +1,402 @@
+-- original file : ftp.lua
+-- for more into : see util-soc.lua
+
+local setmetatable, type, next = setmetatable, type, next
+local find, format, gsub, match = string.find, string.format, string.gsub, string.match
+local concat = table.concat
+local mod = math.mod
+
+local socket = socket or require("socket")
+local url = socket.url or require("socket.url")
+local tp = socket.tp or require("socket.tp")
+local ltn12 = ltn12 or require("ltn12")
+
+local tcpsocket = socket.tcp
+local trysocket = socket.try
+local skipsocket = socket.skip
+local sinksocket = socket.sink
+local selectsocket = socket.select
+local bindsocket = socket.bind
+local newtrysocket = socket.newtry
+local sourcesocket = socket.source
+local protectsocket = socket.protect
+
+local parseurl = url.parse
+local unescapeurl = url.unescape
+
+local pumpall = ltn12.pump.all
+local pumpstep = ltn12.pump.step
+local sourcestring = ltn12.source.string
+local sinktable = ltn12.sink.table
+
+local ftp = {
+ TIMEOUT = 60,
+ USER = "ftp",
+ PASSWORD = "anonymous@anonymous.org",
+}
+
+socket.ftp = ftp
+
+local PORT = 21
+
+local methods = { }
+local mt = { __index = methods }
+
+function ftp.open(server, port, create)
+ local tp = trysocket(tp.connect(server, port or PORT, ftp.TIMEOUT, create))
+ local f = setmetatable({ tp = tp }, metat)
+ f.try = newtrysocket(function() f:close() end)
+ return f
+end
+
+function methods.portconnect(self)
+ local try = self.try
+ local server = self.server
+ try(server:settimeout(ftp.TIMEOUT))
+ self.data = try(server:accept())
+ try(self.data:settimeout(ftp.TIMEOUT))
+end
+
+function methods.pasvconnect(self)
+ local try = self.try
+ self.data = try(tcpsocket())
+ self(self.data:settimeout(ftp.TIMEOUT))
+ self(self.data:connect(self.pasvt.address, self.pasvt.port))
+end
+
+function methods.login(self, user, password)
+ local try = self.try
+ local tp = self.tp
+ try(tp:command("user", user or ftp.USER))
+ local code, reply = try(tp:check{"2..", 331})
+ if code == 331 then
+ try(tp:command("pass", password or ftp.PASSWORD))
+ try(tp:check("2.."))
+ end
+ return 1
+end
+
+function methods.pasv(self)
+ local try = self.try
+ local tp = self.tp
+ try(tp:command("pasv"))
+ local code, reply = try(self.tp:check("2.."))
+ local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)"
+ local a, b, c, d, p1, p2 = skipsocket(2, find(reply, pattern))
+ try(a and b and c and d and p1 and p2, reply)
+ local address = format("%d.%d.%d.%d", a, b, c, d)
+ local port = p1*256 + p2
+ local server = self.server
+ self.pasvt = {
+ address = address,
+ port = port,
+ }
+ if server then
+ server:close()
+ self.server = nil
+ end
+ return address, port
+end
+
+function methods.epsv(self)
+ local try = self.try
+ local tp = self.tp
+ try(tp:command("epsv"))
+ local code, reply = try(tp:check("229"))
+ local pattern = "%((.)(.-)%1(.-)%1(.-)%1%)"
+ local d, prt, address, port = match(reply, pattern)
+ try(port, "invalid epsv response")
+ local address = tp:getpeername()
+ local server = self.server
+ self.pasvt = {
+ address = address,
+ port = port,
+ }
+ if self.server then
+ server:close()
+ self.server = nil
+ end
+ return address, port
+end
+
+function methods.port(self, address, port)
+ local try = self.try
+ local tp = self.tp
+ self.pasvt = nil
+ if not address then
+ address, port = try(tp:getsockname())
+ self.server = try(bindsocket(address, 0))
+ address, port = try(self.server:getsockname())
+ try(self.server:settimeout(ftp.TIMEOUT))
+ end
+ local pl = mod(port,256)
+ local ph = (port - pl)/256
+ local arg = gsub(format("%s,%d,%d", address, ph, pl), "%.", ",")
+ try(tp:command("port", arg))
+ try(tp:check("2.."))
+ return 1
+end
+
+function methods.eprt(self, family, address, port)
+ local try = self.try
+ local tp = self.tp
+ self.pasvt = nil
+ if not address then
+ address, port = try(tp:getsockname())
+ self.server = try(bindsocket(address, 0))
+ address, port = try(self.server:getsockname())
+ try(self.server:settimeout(ftp.TIMEOUT))
+ end
+ local arg = format("|%s|%s|%d|", family, address, port)
+ try(tp:command("eprt", arg))
+ try(tp:check("2.."))
+ return 1
+end
+
+function methods.send(self, sendt)
+ local try = self.try
+ local tp = self.tp
+ -- so we try a table or string ?
+ try(self.pasvt or self.server, "need port or pasv first")
+ if self.pasvt then
+ self:pasvconnect()
+ end
+ local argument = sendt.argument or unescapeurl(gsub(sendt.path or "", "^[/\\]", ""))
+ if argument == "" then
+ argument = nil
+ end
+ local command = sendt.command or "stor"
+ try(tp:command(command, argument))
+ local code, reply = try(tp:check{"2..", "1.."})
+ if not self.pasvt then
+ self:portconnect()
+ end
+ local step = sendt.step or pumpstep
+ local readt = { tp }
+ local checkstep = function(src, snk)
+ local readyt = selectsocket(readt, nil, 0)
+ if readyt[tp] then
+ code = try(tp:check("2.."))
+ end
+ return step(src, snk)
+ end
+ local sink = sinksocket("close-when-done", self.data)
+ try(pumpall(sendt.source, sink, checkstep))
+ if find(code, "1..") then
+ try(tp:check("2.."))
+ end
+ self.data:close()
+ local sent = skipsocket(1, self.data:getstats())
+ self.data = nil
+ return sent
+end
+
+function methods.receive(self, recvt)
+ local try = self.try
+ local tp = self.tp
+ try(self.pasvt or self.server, "need port or pasv first")
+ if self.pasvt then self:pasvconnect() end
+ local argument = recvt.argument or unescapeurl(gsub(recvt.path or "", "^[/\\]", ""))
+ if argument == "" then
+ argument = nil
+ end
+ local command = recvt.command or "retr"
+ try(tp:command(command, argument))
+ local code,reply = try(tp:check{"1..", "2.."})
+ if code >= 200 and code <= 299 then
+ recvt.sink(reply)
+ return 1
+ end
+ if not self.pasvt then
+ self:portconnect()
+ end
+ local source = sourcesocket("until-closed", self.data)
+ local step = recvt.step or pumpstep
+ try(pumpall(source, recvt.sink, step))
+ if find(code, "1..") then
+ try(tp:check("2.."))
+ end
+ self.data:close()
+ self.data = nil
+ return 1
+end
+
+function methods.cwd(self, dir)
+ local try = self.try
+ local tp = self.tp
+ try(tp:command("cwd", dir))
+ try(tp:check(250))
+ return 1
+end
+
+function methods.type(self, typ)
+ local try = self.try
+ local tp = self.tp
+ try(tp:command("type", typ))
+ try(tp:check(200))
+ return 1
+end
+
+function methods.greet(self)
+ local try = self.try
+ local tp = self.tp
+ local code = try(tp:check{"1..", "2.."})
+ if find(code, "1..") then
+ try(tp:check("2.."))
+ end
+ return 1
+end
+
+function methods.quit(self)
+ local try = self.try
+ try(self.tp:command("quit"))
+ try(self.tp:check("2.."))
+ return 1
+end
+
+function methods.close(self)
+ local data = self.data
+ if data then
+ data:close()
+ end
+ local server = self.server
+ if server then
+ server:close()
+ end
+ local tp = self.tp
+ if tp then
+ tp:close()
+ end
+end
+
+local function override(t)
+ if t.url then
+ local u = parseurl(t.url)
+ for k, v in next, t do
+ u[k] = v
+ end
+ return u
+ else
+ return t
+ end
+end
+
+local function tput(putt)
+ putt = override(putt)
+ local host = putt.host
+ trysocket(host, "missing hostname")
+ local f = ftp.open(host, putt.port, putt.create)
+ f:greet()
+ f:login(putt.user, putt.password)
+ local typ = putt.type
+ if typ then
+ f:type(typ)
+ end
+ f:epsv()
+ local sent = f:send(putt)
+ f:quit()
+ f:close()
+ return sent
+end
+
+local default = {
+ path = "/",
+ scheme = "ftp",
+}
+
+local function genericform(u)
+ local t = trysocket(parseurl(u, default))
+ trysocket(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'")
+ trysocket(t.host, "missing hostname")
+ local pat = "^type=(.)$"
+ if t.params then
+ local typ = skipsocket(2, find(t.params, pat))
+ t.type = typ
+ trysocket(typ == "a" or typ == "i", "invalid type '" .. typ .. "'")
+ end
+ return t
+end
+
+ftp.genericform = genericform
+
+local function sput(u, body)
+ local putt = genericform(u)
+ putt.source = sourcestring(body)
+ return tput(putt)
+end
+
+ftp.put = protectsocket(function(putt, body)
+ if type(putt) == "string" then
+ return sput(putt, body)
+ else
+ return tput(putt)
+ end
+end)
+
+local function tget(gett)
+ gett = override(gett)
+ local host = gett.host
+ trysocket(host, "missing hostname")
+ local f = ftp.open(host, gett.port, gett.create)
+ f:greet()
+ f:login(gett.user, gett.password)
+ if gett.type then
+ f:type(gett.type)
+ end
+ f:epsv()
+ f:receive(gett)
+ f:quit()
+ return f:close()
+end
+
+local function sget(u)
+ local gett = genericform(u)
+ local t = { }
+ gett.sink = sinktable(t)
+ tget(gett)
+ return concat(t)
+end
+
+ftp.command = protectsocket(function(cmdt)
+ cmdt = override(cmdt)
+ local command = cmdt.command
+ local argument = cmdt.argument
+ local check = cmdt.check
+ local host = cmdt.host
+ trysocket(host, "missing hostname")
+ trysocket(command, "missing command")
+ local f = ftp.open(host, cmdt.port, cmdt.create)
+ local try = f.try
+ local tp = f.tp
+ f:greet()
+ f:login(cmdt.user, cmdt.password)
+ if type(command) == "table" then
+ local argument = argument or { }
+ for i=1,#command do
+ local cmd = command[i]
+ try(tp:command(cmd, argument[i]))
+ if check and check[i] then
+ try(tp:check(check[i]))
+ end
+ end
+ else
+ try(tp:command(command, argument))
+ if check then
+ try(tp:check(check))
+ end
+ end
+ f:quit()
+ return f:close()
+end)
+
+ftp.get = protectsocket(function(gett)
+ if type(gett) == "string" then
+ return sget(gett)
+ else
+ return tget(gett)
+ end
+end)
+
+package.loaded["socket.ftp"] = ftp
+
+return ftp
diff --git a/tex/context/base/mkiv/util-soc-imp-headers.lua b/tex/context/base/mkiv/util-soc-imp-headers.lua
new file mode 100644
index 000000000..ef51910a5
--- /dev/null
+++ b/tex/context/base/mkiv/util-soc-imp-headers.lua
@@ -0,0 +1,145 @@
+-- original file : headers.lua
+-- for more into : see util-soc.lua
+
+local next = next
+local lower = string.lower
+local concat = table.concat
+
+local socket = socket or require("socket")
+
+local headers = { }
+socket.headers = headers
+
+local canonic = {
+ ["accept"] = "Accept",
+ ["accept-charset"] = "Accept-Charset",
+ ["accept-encoding"] = "Accept-Encoding",
+ ["accept-language"] = "Accept-Language",
+ ["accept-ranges"] = "Accept-Ranges",
+ ["action"] = "Action",
+ ["alternate-recipient"] = "Alternate-Recipient",
+ ["age"] = "Age",
+ ["allow"] = "Allow",
+ ["arrival-date"] = "Arrival-Date",
+ ["authorization"] = "Authorization",
+ ["bcc"] = "Bcc",
+ ["cache-control"] = "Cache-Control",
+ ["cc"] = "Cc",
+ ["comments"] = "Comments",
+ ["connection"] = "Connection",
+ ["content-description"] = "Content-Description",
+ ["content-disposition"] = "Content-Disposition",
+ ["content-encoding"] = "Content-Encoding",
+ ["content-id"] = "Content-ID",
+ ["content-language"] = "Content-Language",
+ ["content-length"] = "Content-Length",
+ ["content-location"] = "Content-Location",
+ ["content-md5"] = "Content-MD5",
+ ["content-range"] = "Content-Range",
+ ["content-transfer-encoding"] = "Content-Transfer-Encoding",
+ ["content-type"] = "Content-Type",
+ ["cookie"] = "Cookie",
+ ["date"] = "Date",
+ ["diagnostic-code"] = "Diagnostic-Code",
+ ["dsn-gateway"] = "DSN-Gateway",
+ ["etag"] = "ETag",
+ ["expect"] = "Expect",
+ ["expires"] = "Expires",
+ ["final-log-id"] = "Final-Log-ID",
+ ["final-recipient"] = "Final-Recipient",
+ ["from"] = "From",
+ ["host"] = "Host",
+ ["if-match"] = "If-Match",
+ ["if-modified-since"] = "If-Modified-Since",
+ ["if-none-match"] = "If-None-Match",
+ ["if-range"] = "If-Range",
+ ["if-unmodified-since"] = "If-Unmodified-Since",
+ ["in-reply-to"] = "In-Reply-To",
+ ["keywords"] = "Keywords",
+ ["last-attempt-date"] = "Last-Attempt-Date",
+ ["last-modified"] = "Last-Modified",
+ ["location"] = "Location",
+ ["max-forwards"] = "Max-Forwards",
+ ["message-id"] = "Message-ID",
+ ["mime-version"] = "MIME-Version",
+ ["original-envelope-id"] = "Original-Envelope-ID",
+ ["original-recipient"] = "Original-Recipient",
+ ["pragma"] = "Pragma",
+ ["proxy-authenticate"] = "Proxy-Authenticate",
+ ["proxy-authorization"] = "Proxy-Authorization",
+ ["range"] = "Range",
+ ["received"] = "Received",
+ ["received-from-mta"] = "Received-From-MTA",
+ ["references"] = "References",
+ ["referer"] = "Referer",
+ ["remote-mta"] = "Remote-MTA",
+ ["reply-to"] = "Reply-To",
+ ["reporting-mta"] = "Reporting-MTA",
+ ["resent-bcc"] = "Resent-Bcc",
+ ["resent-cc"] = "Resent-Cc",
+ ["resent-date"] = "Resent-Date",
+ ["resent-from"] = "Resent-From",
+ ["resent-message-id"] = "Resent-Message-ID",
+ ["resent-reply-to"] = "Resent-Reply-To",
+ ["resent-sender"] = "Resent-Sender",
+ ["resent-to"] = "Resent-To",
+ ["retry-after"] = "Retry-After",
+ ["return-path"] = "Return-Path",
+ ["sender"] = "Sender",
+ ["server"] = "Server",
+ ["smtp-remote-recipient"] = "SMTP-Remote-Recipient",
+ ["status"] = "Status",
+ ["subject"] = "Subject",
+ ["te"] = "TE",
+ ["to"] = "To",
+ ["trailer"] = "Trailer",
+ ["transfer-encoding"] = "Transfer-Encoding",
+ ["upgrade"] = "Upgrade",
+ ["user-agent"] = "User-Agent",
+ ["vary"] = "Vary",
+ ["via"] = "Via",
+ ["warning"] = "Warning",
+ ["will-retry-until"] = "Will-Retry-Until",
+ ["www-authenticate"] = "WWW-Authenticate",
+ ["x-mailer"] = "X-Mailer",
+}
+
+headers.canonic = setmetatable(canonic, {
+ __index = function(t,k)
+ socket.report("invalid header: %s",k)
+ t[k] = k
+ return k
+ end
+})
+
+function headers.normalize(headers)
+ if not headers then
+ return { }
+ end
+ local normalized = { }
+ for k, v in next, headers do
+ normalized[#normalized+1] = canonic[k] .. ": " .. v
+ end
+ normalized[#normalized+1] = ""
+ normalized[#normalized+1] = ""
+ return concat(normalized,"\r\n")
+end
+
+function headers.lower(lowered,headers)
+ if not lowered then
+ return { }
+ end
+ if not headers then
+ lowered, headers = { }, lowered
+ end
+ for k, v in next, headers do
+ lowered[lower(k)] = v
+ end
+ return lowered
+end
+
+socket.headers = headers
+
+package.loaded["socket.headers"] = headers
+
+return headers
diff --git a/tex/context/base/mkiv/util-soc-imp-http.lua b/tex/context/base/mkiv/util-soc-imp-http.lua
new file mode 100644
index 000000000..c3a28be82
--- /dev/null
+++ b/tex/context/base/mkiv/util-soc-imp-http.lua
@@ -0,0 +1,436 @@
+-- original file : http.lua
+-- for more into : see util-soc.lua
+
+local tostring, tonumber, setmetatable, next, type = tostring, tonumber, setmetatable, next, type
+local find, lower, format, gsub, match = string.find, string.lower, string.format, string.gsub, string.match
+local concat = table.concat
+
+local socket = socket or require("socket")
+local url = socket.url or require("socket.url")
+local ltn12 = ltn12 or require("ltn12")
+local mime = mime or require("mime")
+local headers = socket.headers or require("socket.headers")
+
+local normalizeheaders = headers.normalize
+
+local parseurl = url.parse
+local buildurl = url.build
+local absoluteurl = url.absolute
+local unescapeurl = url.unescape
+
+local skipsocket = socket.skip
+local sinksocket = socket.sink
+local sourcesocket = socket.source
+local trysocket = socket.try
+local tcpsocket = socket.tcp
+local newtrysocket = socket.newtry
+local protectsocket = socket.protect
+
+local emptysource = ltn12.source.empty
+local stringsource = ltn12.source.string
+local rewindsource = ltn12.source.rewind
+local pumpstep = ltn12.pump.step
+local pumpall = ltn12.pump.all
+local sinknull = ltn12.sink.null
+local sinktable = ltn12.sink.table
+
+local lowerheaders = headers.lower
+
+local mimeb64 = mime.b64
+
+-- todo: localize ltn12
+
+local http = {
+ TIMEOUT = 60, -- connection timeout in seconds
+ USERAGENT = socket._VERSION, -- user agent field sent in request
+}
+
+socket.http = http
+
+local PORT = 80
+local SCHEMES = {
+ http = true,
+}
+
+-- Reads MIME headers from a connection, unfolding where needed
+
+local function receiveheaders(sock, headers)
+ if not headers then
+ headers = { }
+ end
+ -- get first line
+ local line, err = sock:receive()
+ if err then
+ return nil, err
+ end
+ -- headers go until a blank line is found
+ while line ~= "" do
+ -- get field-name and value
+ local name, value = skipsocket(2, find(line, "^(.-):%s*(.*)"))
+ if not (name and value) then
+ return nil, "malformed reponse headers"
+ end
+ name = lower(name)
+ -- get next line (value might be folded)
+ line, err = sock:receive()
+ if err then
+ return nil, err
+ end
+ -- unfold any folded values
+ while find(line, "^%s") do
+ value = value .. line
+ line = sock:receive()
+ if err then
+ return nil, err
+ end
+ end
+ -- save pair in table
+ local found = headers[name]
+ if found then
+ value = found .. ", " .. value
+ end
+ headers[name] = value
+ end
+ return headers
+end
+
+-- Extra sources and sinks
+
+socket.sourcet["http-chunked"] = function(sock, headers)
+ return setmetatable (
+ {
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end,
+ }, {
+ __call = function()
+ local line, err = sock:receive()
+ if err then
+ return nil, err
+ end
+ local size = tonumber(gsub(line, ";.*", ""), 16)
+ if not size then
+ return nil, "invalid chunk size"
+ end
+ if size > 0 then
+ local chunk, err, part = sock:receive(size)
+ if chunk then
+ sock:receive()
+ end
+ return chunk, err
+ else
+ headers, err = receiveheaders(sock, headers)
+ if not headers then
+ return nil, err
+ end
+ end
+ end
+ }
+ )
+end
+
+socket.sinkt["http-chunked"] = function(sock)
+ return setmetatable(
+ {
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end,
+ },
+ {
+ __call = function(self, chunk, err)
+ if not chunk then
+ chunk = ""
+ end
+ return sock:send(format("%X\r\n%s\r\n",#chunk,chunk))
+ end
+ })
+end
+
+-- Low level HTTP API
+
+local methods = { }
+local mt = { __index = methods }
+
+local function openhttp(host, port, create)
+ local c = trysocket((create or tcpsocket)())
+ local h = setmetatable({ c = c }, mt)
+ local try = newtrysocket(function() h:close() end)
+ h.try = try
+ try(c:settimeout(http.TIMEOUT))
+ try(c:connect(host, port or PORT))
+ return h
+end
+
+http.open = openhttp
+
+function methods.sendrequestline(self, method, uri)
+ local requestline = format("%s %s HTTP/1.1\r\n", method or "GET", uri)
+ return self.try(self.c:send(requestline))
+end
+
+function methods.sendheaders(self,headers)
+ self.try(self.c:send(normalizeheaders(headers)))
+ return 1
+end
+
+function methods.sendbody(self, headers, source, step)
+ if not source then
+ source = emptysource()
+ end
+ if not step then
+ step = pumpstep
+ end
+ local mode = "http-chunked"
+ if headers["content-length"] then
+ mode = "keep-open"
+ end
+ return self.try(pumpall(source, sinksocket(mode, self.c), step))
+end
+
+function methods.receivestatusline(self)
+ local try = self.try
+ local status = try(self.c:receive(5))
+ if status ~= "HTTP/" then
+ return nil, status -- HTTP/0.9
+ end
+ status = try(self.c:receive("*l", status))
+ local code = skipsocket(2, find(status, "HTTP/%d*%.%d* (%d%d%d)"))
+ return try(tonumber(code), status)
+end
+
+function methods.receiveheaders(self)
+ return self.try(receiveheaders(self.c))
+end
+
+function methods.receivebody(self, headers, sink, step)
+ if not sink then
+ sink = sinknull()
+ end
+ if not step then
+ step = pumpstep
+ end
+ local length = tonumber(headers["content-length"])
+ local encoding = headers["transfer-encoding"] -- shortcut
+ local mode = "default" -- connection close
+ if encoding and encoding ~= "identity" then
+ mode = "http-chunked"
+ elseif length then
+ mode = "by-length"
+ end
+ --hh: so length can be nil
+ return self.try(pumpall(sourcesocket(mode, self.c, length), sink, step))
+end
+
+function methods.receive09body(self, status, sink, step)
+ local source = rewindsource(sourcesocket("until-closed", self.c))
+ source(status)
+ return self.try(pumpall(source, sink, step))
+end
+
+function methods.close(self)
+ return self.c:close()
+end
+
+-- High level HTTP API
+
+local function adjusturi(request)
+ if not request.proxy and not http.PROXY then
+ request = {
+ path = trysocket(request.path, "invalid path 'nil'"),
+ params = request.params,
+ query = request.query,
+ fragment = request.fragment,
+ }
+ end
+ return buildurl(request)
+end
+
+local function adjustheaders(request)
+ local headers = {
+ ["user-agent"] = http.USERAGENT,
+ ["host"] = gsub(request.authority, "^.-@", ""),
+ ["connection"] = "close, TE",
+ ["te"] = "trailers"
+ }
+ local username = request.user
+ local password = request.password
+ if username and password then
+ headers["authorization"] = "Basic " .. (mimeb64(username .. ":" .. unescapeurl(password)))
+ end
+ local proxy = request.proxy or http.PROXY
+ if proxy then
+ proxy = parseurl(proxy)
+ local username = proxy.user
+ local password = proxy.password
+ if username and password then
+ headers["proxy-authorization"] = "Basic " .. (mimeb64(username .. ":" .. password))
+ end
+ end
+ local requestheaders = request.headers
+ if requestheaders then
+ headers = lowerheaders(headers,requestheaders)
+ end
+ return headers
+end
+
+-- default url parts
+
+local default = {
+ host = "",
+ port = PORT,
+ path = "/",
+ scheme = "http"
+}
+
+local function adjustrequest(originalrequest)
+ local url = originalrequest.url
+ local request = url and parseurl(url,default) or { }
+ for k, v in next, originalrequest do
+ request[k] = v
+ end
+ local host = request.host
+ local port = request.port
+ local uri = request.uri
+ if not host or host == "" then
+ trysocket(nil, "invalid host '" .. tostring(host) .. "'")
+ end
+ if port == "" then
+ request.port = PORT
+ end
+ if not uri or uri == "" then
+ request.uri = adjusturi(request)
+ end
+ request.headers = adjustheaders(request)
+ local proxy = request.proxy or http.PROXY
+ if proxy then
+ proxy = parseurl(proxy)
+ request.host = proxy.host
+ request.port = proxy.port or 3128
+ end
+ return request
+end
+
+local maxredericts = 4
+local validredirects = { [301] = true, [302] = true, [303] = true, [307] = true }
+local validmethods = { [false] = true, GET = true, HEAD = true }
+
+local function shouldredirect(request, code, headers)
+ local location = headers.location
+ if not location then
+ return false
+ end
+ location = gsub(location, "%s", "")
+ if location == "" then
+ return false
+ end
+ local scheme = match(location, "^([%w][%w%+%-%.]*)%:")
+ if scheme and not SCHEMES[scheme] then
+ return false
+ end
+ local method = request.method
+ local redirect = request.redirect
+ local redirects = request.nredirects or 0
+ return redirect and validredirects[code] and validmethods[method] and redirects <= maxredericts
+end
+
+local function shouldreceivebody(request, code)
+ if request.method == "HEAD" then
+ return nil
+ end
+ if code == 204 or code == 304 then
+ return nil
+ end
+ if code >= 100 and code < 200 then
+ return nil
+ end
+ return 1
+end
+
+local tredirect, trequest, srequest
+
+tredirect = function(request, location)
+ local result, code, headers, status = trequest {
+ url = absoluteurl(request.url,location),
+ source = request.source,
+ sink = request.sink,
+ headers = request.headers,
+ proxy = request.proxy,
+ nredirects = (request.nredirects or 0) + 1,
+ create = request.create,
+ }
+ if not headers then
+ headers = { }
+ end
+ if not headers.location then
+ headers.location = location
+ end
+ return result, code, headers, status
+end
+
+trequest = function(originalrequest)
+ local request = adjustrequest(originalrequest)
+ local connection = openhttp(request.host, request.port, request.create)
+ local headers = request.headers
+ connection:sendrequestline(request.method, request.uri)
+ connection:sendheaders(headers)
+ if request.source then
+ connection:sendbody(headers, request.source, request.step)
+ end
+ local code, status = connection:receivestatusline()
+ if not code then
+ connection:receive09body(status, request.sink, request.step)
+ return 1, 200
+ end
+ while code == 100 do
+ headers = connection:receiveheaders()
+ code, status = connection:receivestatusline()
+ end
+ headers = connection:receiveheaders()
+ if shouldredirect(request, code, headers) and not request.source then
+ connection:close()
+ return tredirect(originalrequest,headers.location)
+ end
+ if shouldreceivebody(request, code) then
+ connection:receivebody(headers, request.sink, request.step)
+ end
+ connection:close()
+ return 1, code, headers, status
+end
+
+-- turns an url and a body into a generic request
+
+local function genericform(url, body)
+ local buffer = { }
+ local request = {
+ url = url,
+ sink = sinktable(buffer),
+ target = buffer,
+ }
+ if body then
+ request.source = stringsource(body)
+ request.method = "POST"
+ request.headers = {
+ ["content-length"] = #body,
+ ["content-type"] = "application/x-www-form-urlencoded"
+ }
+ end
+ return request
+end
+
+http.genericform = genericform
+
+srequest = function(url, body)
+ local request = genericform(url, body)
+ local _, code, headers, status = trequest(request)
+ return concat(request.target), code, headers, status
+end
+
+http.request = protectsocket(function(request, body)
+ if type(request) == "string" then
+ return srequest(request, body)
+ else
+ return trequest(request)
+ end
+end)
+
+package.loaded["socket.http"] = http
+
+return http
diff --git a/tex/context/base/mkiv/util-soc-imp-ltn12.lua b/tex/context/base/mkiv/util-soc-imp-ltn12.lua
new file mode 100644
index 000000000..54110ab7a
--- /dev/null
+++ b/tex/context/base/mkiv/util-soc-imp-ltn12.lua
@@ -0,0 +1,387 @@
+-- original file : ltn12.lua
+-- for more into : see util-soc.lua
+
+local select, unpack = select, unpack
+local insert, remove = table.insert, table.remove
+local sub = string.sub
+
+local function report(fmt,first,...)
+ if logs then
+ report = logs and logs.reporter("ltn12")
+ report(fmt,first,...)
+ elseif fmt then
+ fmt = "ltn12: " .. fmt
+ if first then
+ print(format(fmt,first,...))
+ else
+ print(fmt)
+ end
+ end
+end
+
+local filter = { }
+local source = { }
+local sink = { }
+local pump = { }
+
+local ltn12 = {
+
+ _VERSION = "LTN12 1.0.3",
+
+ BLOCKSIZE = 2048,
+
+ filter = filter,
+ source = source,
+ sink = sink,
+ pump = pump,
+
+ report = report,
+
+}
+
+-- returns a high level filter that cycles a low-level filter
+
+function filter.cycle(low, ctx, extra)
+ if low then
+ return function(chunk)
+ return (low(ctx, chunk, extra))
+ end
+ end
+end
+
+-- chains a bunch of filters together
+
+function filter.chain(...)
+ local arg = { ... }
+ local n = select('#',...)
+ local top = 1
+ local index = 1
+ local retry = ""
+ return function(chunk)
+ retry = chunk and retry
+ while true do
+ local action = arg[index]
+ if index == top then
+ chunk = action(chunk)
+ if chunk == "" or top == n then
+ return chunk
+ elseif chunk then
+ index = index + 1
+ else
+ top = top + 1
+ index = top
+ end
+ else
+ chunk = action(chunk or "")
+ if chunk == "" then
+ index = index - 1
+ chunk = retry
+ elseif chunk then
+ if index == n then
+ return chunk
+ else
+ index = index + 1
+ end
+ else
+ report("error: filter returned inappropriate 'nil'")
+ return
+ end
+ end
+ end
+ end
+end
+
+-- create an empty source
+
+local function empty()
+ return nil
+end
+
+function source.empty()
+ return empty
+end
+
+-- returns a source that just outputs an error
+
+local function sourceerror(err)
+ return function()
+ return nil, err
+ end
+end
+
+source.error = sourceerror
+
+-- creates a file source
+
+function source.file(handle, io_err)
+ if handle then
+ local blocksize = ltn12.BLOCKSIZE
+ return function()
+ local chunk = handle:read(blocksize)
+ if not chunk then
+ handle:close()
+ end
+ return chunk
+ end
+ else
+ return sourceerror(io_err or "unable to open file")
+ end
+end
+
+-- turns a fancy source into a simple source
+
+function source.simplify(src)
+ return function()
+ local chunk, err_or_new = src()
+ if err_or_new then
+ src = err_or_new
+ end
+ if chunk then
+ return chunk
+ else
+ return nil, err_or_new
+ end
+ end
+end
+
+-- creates string source
+
+function source.string(s)
+ if s then
+ local blocksize = ltn12.BLOCKSIZE
+ local i = 1
+ return function()
+ local nexti = i + blocksize
+ local chunk = sub(s, i, nexti - 1)
+ i = nexti
+ if chunk ~= "" then
+ return chunk
+ else
+ return nil
+ end
+ end
+ else return source.empty() end
+end
+
+-- creates rewindable source
+
+function source.rewind(src)
+ local t = { }
+ return function(chunk)
+ if chunk then
+ insert(t, chunk)
+ else
+ chunk = remove(t)
+ if chunk then
+ return chunk
+ else
+ return src()
+ end
+ end
+ end
+end
+
+-- chains a source with one or several filter(s)
+
+function source.chain(src, f, ...)
+ if ... then
+ f = filter.chain(f, ...)
+ end
+ local last_in = ""
+ local last_out = ""
+ local state = "feeding"
+ local err
+ return function()
+ if not last_out then
+ report("error: source is empty")
+ return
+ end
+ while true do
+ if state == "feeding" then
+ last_in, err = src()
+ if err then
+ return nil, err
+ end
+ last_out = f(last_in)
+ if not last_out then
+ if last_in then
+ report("error: filter returned inappropriate 'nil'")
+ end
+ return nil
+ elseif last_out ~= "" then
+ state = "eating"
+ if last_in then
+ last_in = ""
+ end
+ return last_out
+ end
+ else
+ last_out = f(last_in)
+ if last_out == "" then
+ if last_in == "" then
+ state = "feeding"
+ else
+ report("error: filter returned nothing")
+ return
+ end
+ elseif not last_out then
+ if last_in then
+ report("filter returned inappropriate 'nil'")
+ end
+ return nil
+ else
+ return last_out
+ end
+ end
+ end
+ end
+end
+
+-- creates a source that produces contents of several sources, one after the
+-- other, as if they were concatenated
+
+function source.cat(...)
+ local arg = { ... }
+ local src = remove(arg,1)
+ return function()
+ while src do
+ local chunk, err = src()
+ if chunk then
+ return chunk
+ end
+ if err then
+ return nil, err
+ end
+ src = remove(arg,1)
+ end
+ end
+end
+
+-- creates a sink that stores into a table
+
+function sink.table(t)
+ if not t then
+ t = { }
+ end
+ local f = function(chunk, err)
+ if chunk then
+ insert(t, chunk)
+ end
+ return 1
+ end
+ return f, t
+end
+
+-- turns a fancy sink into a simple sink
+
+function sink.simplify(snk)
+ return function(chunk, err)
+ local ret, err_or_new = snk(chunk, err)
+ if not ret then
+ return nil, err_or_new
+ end
+ if err_or_new then
+ snk = err_or_new
+ end
+ return 1
+ end
+end
+
+-- creates a sink that discards data
+
+local function null()
+ return 1
+end
+
+function sink.null()
+ return null
+end
+
+-- creates a sink that just returns an error
+
+local function sinkerror(err)
+ return function()
+ return nil, err
+ end
+end
+
+sink.error = sinkerror
+
+-- creates a file sink
+
+function sink.file(handle, io_err)
+ if handle then
+ return function(chunk, err)
+ if not chunk then
+ handle:close()
+ return 1
+ else
+ return handle:write(chunk)
+ end
+ end
+ else
+ return sinkerror(io_err or "unable to open file")
+ end
+end
+
+-- chains a sink with one or several filter(s)
+
+function sink.chain(f, snk, ...)
+ if ... then
+ local args = { f, snk, ... }
+ snk = remove(args, #args)
+ f = filter.chain(unpack(args))
+ end
+ return function(chunk, err)
+ if chunk ~= "" then
+ local filtered = f(chunk)
+ local done = chunk and ""
+ while true do
+ local ret, snkerr = snk(filtered, err)
+ if not ret then
+ return nil, snkerr
+ end
+ if filtered == done then
+ return 1
+ end
+ filtered = f(done)
+ end
+ else
+ return 1
+ end
+ end
+end
+
+-- pumps one chunk from the source to the sink
+
+function pump.step(src, snk)
+ local chunk, src_err = src()
+ local ret, snk_err = snk(chunk, src_err)
+ if chunk and ret then
+ return 1
+ else
+ return nil, src_err or snk_err
+ end
+end
+
+-- pumps all data from a source to a sink, using a step function
+
+function pump.all(src, snk, step)
+ if not step then
+ step = pump.step
+ end
+ while true do
+ local ret, err = step(src, snk)
+ if not ret then
+ if err then
+ return nil, err
+ else
+ return 1
+ end
+ end
+ end
+end
+
+package.loaded["ltn12"] = ltn12
+
+return ltn12
diff --git a/tex/context/base/mkiv/util-soc-imp-mime.lua b/tex/context/base/mkiv/util-soc-imp-mime.lua
new file mode 100644
index 000000000..4b5d2baff
--- /dev/null
+++ b/tex/context/base/mkiv/util-soc-imp-mime.lua
@@ -0,0 +1,104 @@
+-- original file : mime.lua
+-- for more into : see util-soc.lua
+
+local type, tostring = type, tostring
+
+local mime = require("mime.core")
+local ltn12 = ltn12 or require("ltn12")
+
+local filtercycle = ltn12.filter.cycle
+
+local function report(fmt,first,...)
+ if logs then
+ report = logs and logs.reporter("mime")
+ report(fmt,first,...)
+ elseif fmt then
+ fmt = "mime: " .. fmt
+ if first then
+ print(format(fmt,first,...))
+ else
+ print(fmt)
+ end
+ end
+end
+
+mime.report = report
+
+local encodet = { }
+local decodet = { }
+local wrapt = { }
+
+mime.encodet = encodet
+mime.decodet = decodet
+mime.wrapt = wrapt
+
+local mime_b64 = mime.b64
+local mime_qp = mime.qp
+local mime_unb64 = mime.unb64
+local mime_unqp = mime.unqp
+local mime_wrp = mime.wrp
+local mime_qpwrp = mime.qpwrp
+local mime_eol = mime_eol
+local mime_dot = mime_dot
+
+encodet['base64'] = function()
+ return filtercycle(mime_b64,"")
+end
+
+encodet['quoted-printable'] = function(mode)
+ return filtercycle(mime_qp, "", mode == "binary" and "=0D=0A" or "\r\n")
+end
+
+decodet['base64'] = function()
+ return filtercycle(mime_unb64, "")
+end
+
+decodet['quoted-printable'] = function()
+ return filtercycle(mime_unqp, "")
+end
+
+local wraptext = function(length)
+ if not length then
+ length = 76
+ end
+ return filtercycle(mime_wrp, length, length)
+end
+
+local wrapquoted = function()
+ return filtercycle(mime_qpwrp, 76, 76)
+end
+
+wrapt['text'] = wraptext
+wrapt['base64'] = wraptext
+wrapt['default'] = wraptext
+wrapt['quoted-printable'] = wrapquoted
+
+function mime.normalize(marker)
+ return filtercycle(mime_eol, 0, marker)
+end
+
+function mime.stuff()
+ return filtercycle(mime_dot, 2)
+end
+
+local function choose(list)
+ return function(name, opt1, opt2)
+ if type(name) ~= "string" then
+ name, opt1, opt2 = "default", name, opt1
+ end
+ local filter = list[name or "nil"]
+ if filter then
+ return filter(opt1, opt2)
+ else
+ report("error: unknown key '%s'",tostring(name))
+ end
+ end
+end
+
+mime.encode = choose(encodet)
+mime.decode = choose(decodet)
+mime.wrap = choose(wrapt)
+
+package.loaded["mime"] = mime
+
+return mime
diff --git a/tex/context/base/mkiv/util-soc-imp-reset.lua b/tex/context/base/mkiv/util-soc-imp-reset.lua
new file mode 100644
index 000000000..a4a489b0f
--- /dev/null
+++ b/tex/context/base/mkiv/util-soc-imp-reset.lua
@@ -0,0 +1,13 @@
+local loaded = package.loaded
+
+loaded["socket"] = nil
+loaded["copas"] = nil
+loaded["ltn12"] = nil
+loaded["mbox"] = nil
+loaded["mime"] = nil
+loaded["socket.url"] = nil
+loaded["socket.headers"] = nil
+loaded["socket.tp"] = nil
+loaded["socket.http"] = nil
+loaded["socket.ftp"] = nil
+loaded["socket.smtp"] = nil
diff --git a/tex/context/base/mkiv/util-soc-imp-smtp.lua b/tex/context/base/mkiv/util-soc-imp-smtp.lua
new file mode 100644
index 000000000..621d1b6e3
--- /dev/null
+++ b/tex/context/base/mkiv/util-soc-imp-smtp.lua
@@ -0,0 +1,267 @@
+-- original file : smtp.lua
+-- for more into : see util-soc.lua
+
+local type, setmetatable, next = type, setmetatable, next
+local find, lower, format = string.find, string.lower, string.format
+local osdate, osgetenv = os.date, os.getenv
+local random = math.random
+
+local socket = socket or require("socket")
+local headers = socket.headers or require("socket.headers")
+local ltn12 = ltn12 or require("ltn12")
+local tp = socket.tp or require("socket.tp")
+local mime = mime or require("mime")
+
+local mimeb64 = mime.b64
+local mimestuff = mime.stuff
+
+local skipsocket = socket.skip
+local trysocket = socket.try
+local newtrysocket = socket.newtry
+local protectsocket = socket.protect
+
+local normalizeheaders = headers.normalize
+local lowerheaders = headers.lower
+
+local createcoroutine = coroutine.create
+local resumecoroutine = coroutine.resume
+local yieldcoroutine = coroutine.resume
+
+local smtp = {
+ TIMEOUT = 60,
+ SERVER = "localhost",
+ PORT = 25,
+ DOMAIN = osgetenv("SERVER_NAME") or "localhost",
+ ZONE = "-0000",
+}
+
+socket.smtp = smtp
+
+local methods = { }
+local mt = { __index = methods }
+
+function methods.greet(self, domain)
+ local try = self.try
+ local tp = self.tp
+ try(tp:check("2.."))
+ try(tp:command("EHLO", domain or _M.DOMAIN))
+ return skipsocket(1, try(tp:check("2..")))
+end
+
+function methods.mail(self, from)
+ local try = self.try
+ local tp = self.tp
+ try(tp:command("MAIL", "FROM:" .. from))
+ return try(tp:check("2.."))
+end
+
+function methods.rcpt(self, to)
+ local try = self.try
+ local tp = self.tp
+ try(tp:command("RCPT", "TO:" .. to))
+ return try(tp:check("2.."))
+end
+
+function methods.data(self, src, step)
+ local try = self.try
+ local tp = self.tp
+ try(tp:command("DATA"))
+ try(tp:check("3.."))
+ try(tp:source(src, step))
+ try(tp:send("\r\n.\r\n"))
+ return try(tp:check("2.."))
+end
+
+function methods.quit(self)
+ local try = self.try
+ local tp = self.tp
+ try(tp:command("QUIT"))
+ return try(tp:check("2.."))
+end
+
+function methods.close(self)
+ return self.tp:close()
+end
+
+function methods.login(self, user, password)
+ local try = self.try
+ local tp = self.tp
+ try(tp:command("AUTH", "LOGIN"))
+ try(tp:check("3.."))
+ try(tp:send(mimeb64(user) .. "\r\n"))
+ try(tp:check("3.."))
+ try(tp:send(mimeb64(password) .. "\r\n"))
+ return try(tp:check("2.."))
+end
+
+function methods.plain(self, user, password)
+ local try = self.try
+ local tp = self.tp
+ local auth = "PLAIN " .. mimeb64("\0" .. user .. "\0" .. password)
+ try(tp:command("AUTH", auth))
+ return try(tp:check("2.."))
+end
+
+function methods.auth(self, user, password, ext)
+ if not user or not password then
+ return 1
+ end
+ local try = self.try
+ if find(ext, "AUTH[^\n]+LOGIN") then
+ return self:login(user,password)
+ elseif find(ext, "AUTH[^\n]+PLAIN") then
+ return self:plain(user,password)
+ else
+ try(nil, "authentication not supported")
+ end
+end
+
+function methods.send(self, mail)
+ self:mail(mail.from)
+ local receipt = mail.rcpt
+ if type(receipt) == "table" then
+ for i=1,#receipt do
+ self:rcpt(receipt[i])
+ end
+ elseif receipt then
+ self:rcpt(receipt)
+ end
+ self:data(ltn12.source.chain(mail.source, mimestuff()), mail.step)
+end
+
+local function opensmtp(self, server, port, create)
+ if not server or server == "" then
+ server = smtp.SERVER
+ end
+ if not port or port == "" then
+ port = smtp.PORT
+ end
+ local s = {
+ tp = trysocket(tp.connect(server, port, smtp.TIMEOUT, create)),
+ try = newtrysocket(function()
+ s:close()
+ end),
+ }
+ setmetatable(s, mt)
+ return s
+end
+
+smtp.open = opensmtp
+
+local nofboundaries = 0
+
+local function newboundary()
+ nofboundaries = nofboundaries + 1
+ return format('%s%05d==%05u', osdate('%d%m%Y%H%M%S'), random(0,99999), nofboundaries)
+end
+
+local send_message
+
+local function send_headers(headers)
+ yieldcoroutine(normalizeheaders(headers))
+end
+
+local function send_multipart(message)
+ local boundary = newboundary()
+ local headers = lowerheaders(message.headers)
+ local body = message.body
+ local preamble = body.preamble
+ local epilogue = body.epilogue
+ local content = headers['content-type'] or 'multipart/mixed'
+ headers['content-type'] = content .. '; boundary="' .. boundary .. '"'
+ send_headers(headers)
+ if preamble then
+ yieldcoroutine(preamble)
+ yieldcoroutine("\r\n")
+ end
+ for i=1,#body do
+ yieldcoroutine("\r\n--" .. boundary .. "\r\n")
+ send_message(body[i])
+ end
+ yieldcoroutine("\r\n--" .. boundary .. "--\r\n\r\n")
+ if epilogue then
+ yieldcoroutine(epilogue)
+ yieldcoroutine("\r\n")
+ end
+end
+
+local default_content_type = 'text/plain; charset="UTF-8"'
+
+local function send_source(message)
+ local headers = lowerheaders(message.headers)
+ if not headers['content-type'] then
+ headers['content-type'] = default_content_type
+ end
+ send_headers(headers)
+ local getchunk = message.body
+ while true do
+ local chunk, err = getchunk()
+ if err then
+ yieldcoroutine(nil, err)
+ elseif chunk then
+ yieldcoroutine(chunk)
+ else
+ break
+ end
+ end
+end
+
+local function send_string(message)
+ local headers = lowerheaders(message.headers)
+ if not headers['content-type'] then
+ headers['content-type'] = default_content_type
+ end
+ send_headers(headers)
+ yieldcoroutine(message.body)
+end
+
+function send_message(message)
+ local body = message.body
+ if type(body) == "table" then
+ send_multipart(message)
+ elseif type(body) == "function" then
+ send_source(message)
+ else
+ send_string(message)
+ end
+end
+
+local function adjust_headers(message)
+ local headers = lowerheaders(message.headers)
+ if not headers["date"] then
+ headers["date"] = osdate("!%a, %d %b %Y %H:%M:%S ") .. (message.zone or smtp.ZONE)
+ end
+ if not headers["x-mailer"] then
+ headers["x-mailer"] = socket._VERSION
+ end
+ headers["mime-version"] = "1.0"
+ return headers
+end
+
+function smtp.message(message)
+ message.headers = adjust_headers(message)
+ local action = createcoroutine(function()
+ send_message(message)
+ end)
+ return function()
+ local ret, a, b = resumecoroutine(action)
+ if ret then
+ return a, b
+ else
+ return nil, a
+ end
+ end
+end
+
+smtp.send = protectsocket(function(mail)
+ local snd = opensmtp(smtp,mail.server, mail.port, mail.create)
+ local ext = snd:greet(mail.domain)
+ snd:auth(mail.user, mail.password, ext)
+ snd:send(mail)
+ snd:quit()
+ return snd:close()
+end)
+
+package.loaded["socket.smtp"] = smtp
+
+return smtp
diff --git a/tex/context/base/mkiv/util-soc-imp-socket.lua b/tex/context/base/mkiv/util-soc-imp-socket.lua
new file mode 100644
index 000000000..3da155749
--- /dev/null
+++ b/tex/context/base/mkiv/util-soc-imp-socket.lua
@@ -0,0 +1,193 @@
+-- original file : socket.lua
+-- for more into : see util-soc.lua
+
+local type, tostring, setmetatable = type, tostring, setmetatable
+local min = math.min
+local format = string.format
+
+local socket = require("socket.core")
+
+local connect = socket.connect
+local tcp4 = socket.tcp4
+local tcp6 = socket.tcp6
+local getaddrinfo = socket.dns.getaddrinfo
+
+local defaulthost = "0.0.0.0"
+
+local function report(fmt,first,...)
+ if logs then
+ report = logs and logs.reporter("socket")
+ report(fmt,first,...)
+ elseif fmt then
+ fmt = "socket: " .. fmt
+ if first then
+ print(format(fmt,first,...))
+ else
+ print(fmt)
+ end
+ end
+end
+
+socket.report = report
+
+function socket.connect4(address, port, laddress, lport)
+ return connect(address, port, laddress, lport, "inet")
+end
+
+function socket.connect6(address, port, laddress, lport)
+ return connect(address, port, laddress, lport, "inet6")
+end
+
+function socket.bind(host, port, backlog)
+ if host == "*" or host == "" then
+ host = defaulthost
+ end
+ local addrinfo, err = getaddrinfo(host)
+ if not addrinfo then
+ return nil, err
+ end
+ for i=1,#addrinfo do
+ local alt = addrinfo[i]
+ local sock, err = (alt.family == "inet" and tcp4 or tcp6)()
+ if not sock then
+ return nil, err or "unknown error"
+ end
+ sock:setoption("reuseaddr", true)
+ local res, err = sock:bind(alt.addr, port)
+ if res then
+ res, err = sock:listen(backlog)
+ if res then
+ return sock
+ else
+ sock:close()
+ end
+ else
+ sock:close()
+ end
+ end
+ return nil, "invalid address"
+end
+
+socket.try = socket.newtry()
+
+function socket.choose(list)
+ return function(name, opt1, opt2)
+ if type(name) ~= "string" then
+ name, opt1, opt2 = "default", name, opt1
+ end
+ local f = list[name or "nil"]
+ if f then
+ return f(opt1, opt2)
+ else
+ report("error: unknown key '%s'",tostring(name))
+ end
+ end
+end
+
+local sourcet = { }
+local sinkt = { }
+
+socket.sourcet = sourcet
+socket.sinkt = sinkt
+
+socket.BLOCKSIZE = 2048
+
+sinkt["close-when-done"] = function(sock)
+ return setmetatable (
+ {
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end,
+ },
+ {
+ __call = function(self, chunk, err)
+ if chunk then
+ return sock:send(chunk)
+ else
+ sock:close()
+ return 1 -- why 1
+ end
+ end
+ }
+ )
+end
+
+sinkt["keep-open"] = function(sock)
+ return setmetatable (
+ {
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end,
+ }, {
+ __call = function(self, chunk, err)
+ if chunk then
+ return sock:send(chunk)
+ else
+ return 1 -- why 1
+ end
+ end
+ }
+ )
+end
+
+sinkt["default"] = sinkt["keep-open"]
+
+socket.sink = socket.choose(sinkt)
+
+sourcet["by-length"] = function(sock, length)
+ local blocksize = socket.BLOCKSIZE
+ return setmetatable (
+ {
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end,
+ },
+ {
+ __call = function()
+ if length <= 0 then
+ return nil
+ end
+ local chunk, err = sock:receive(min(blocksize,length))
+ if err then
+ return nil, err
+ end
+ length = length - #chunk
+ return chunk
+ end
+ }
+ )
+end
+
+sourcet["until-closed"] = function(sock)
+ local blocksize = socket.BLOCKSIZE
+ local done = false
+ return setmetatable (
+ {
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end,
+ }, {
+ __call = function()
+ if done then
+ return nil
+ end
+ local chunk, status, partial = sock:receive(blocksize)
+ if not status then
+ return chunk
+ elseif status == "closed" then
+ sock:close()
+ done = true
+ return partial
+ else
+ return nil, status
+ end
+ end
+ }
+ )
+end
+
+sourcet["default"] = sourcet["until-closed"]
+
+socket.source = socket.choose(sourcet)
+
+_G.socket = socket -- for now global
+
+package.loaded["socket"] = socket
+
+return socket
diff --git a/tex/context/base/mkiv/util-soc-imp-tp.lua b/tex/context/base/mkiv/util-soc-imp-tp.lua
new file mode 100644
index 000000000..e651e44f7
--- /dev/null
+++ b/tex/context/base/mkiv/util-soc-imp-tp.lua
@@ -0,0 +1,144 @@
+-- original file : tp.lua
+-- for more into : see util-soc.lua
+
+local setmetatable, next, type, tonumber = setmetatable, next, type, tonumber
+local find, upper = string.find, string.upper
+
+local socket = socket or require("socket")
+local ltn12 = ltn12 or require("ltn12")
+
+local skipsocket = socket.skip
+local sinksocket = socket.sink
+local tcpsocket = socket.tcp
+
+local ltn12pump = ltn12.pump
+local pumpall = ltn12pump.all
+local pumpstep = ltn12pump.step
+
+local tp = {
+ TIMEOUT = 60,
+}
+
+socket.tp = tp
+
+local function get_reply(c)
+ local line, err = c:receive()
+ local reply = line
+ if err then return
+ nil, err
+ end
+ local code, sep = skipsocket(2, find(line, "^(%d%d%d)(.?)"))
+ if not code then
+ return nil, "invalid server reply"
+ end
+ if sep == "-" then
+ local current
+ repeat
+ line, err = c:receive()
+ if err then
+ return nil, err
+ end
+ current, sep = skipsocket(2, find(line, "^(%d%d%d)(.?)"))
+ reply = reply .. "\n" .. line
+ until code == current and sep == " "
+ end
+ return code, reply
+end
+
+local methods = { }
+local mt = { __index = methods }
+
+function methods.getpeername(self)
+ return self.c:getpeername()
+end
+
+function methods.getsockname(self)
+ return self.c:getpeername()
+end
+
+function methods.check(self, ok)
+ local code, reply = get_reply(self.c)
+ if not code then
+ return nil, reply
+ end
+ local c = tonumber(code)
+ local t = type(ok)
+ if t == "function" then
+ return ok(c,reply)
+ elseif t == "table" then
+ for i=1,#ok do
+ if find(code,ok[i]) then
+ return c, reply
+ end
+ end
+ return nil, reply
+ elseif find(code, ok) then
+ return c, reply
+ else
+ return nil, reply
+ end
+end
+
+function methods.command(self, cmd, arg)
+ cmd = upper(cmd)
+ if arg then
+ cmd = cmd .. " " .. arg .. "\r\n"
+ else
+ cmd = cmd .. "\r\n"
+ end
+ return self.c:send(cmd)
+end
+
+function methods.sink(self, snk, pat)
+ local chunk, err = self.c:receive(pat)
+ return snk(chunk, err)
+end
+
+function methods.send(self, data)
+ return self.c:send(data)
+end
+
+function methods.receive(self, pat)
+ return self.c:receive(pat)
+end
+
+function methods.getfd(self)
+ return self.c:getfd()
+end
+
+function methods.dirty(self)
+ return self.c:dirty()
+end
+
+function methods.getcontrol(self)
+ return self.c
+end
+
+function methods.source(self, source, step)
+ local sink = sinksocket("keep-open", self.c)
+ local ret, err = pumpall(source, sink, step or pumpstep)
+ return ret, err
+end
+
+function methods.close(self)
+ self.c:close()
+ return 1
+end
+
+function tp.connect(host, port, timeout, create)
+ local c, e = (create or tcpsocket)()
+ if not c then
+ return nil, e
+ end
+ c:settimeout(timeout or tp.TIMEOUT)
+ local r, e = c:connect(host, port)
+ if not r then
+ c:close()
+ return nil, e
+ end
+ return setmetatable({ c = c }, mt)
+end
+
+package.loaded["socket.tp"] = tp
+
+return tp
diff --git a/tex/context/base/mkiv/util-soc-imp-url.lua b/tex/context/base/mkiv/util-soc-imp-url.lua
new file mode 100644
index 000000000..fa472b650
--- /dev/null
+++ b/tex/context/base/mkiv/util-soc-imp-url.lua
@@ -0,0 +1,268 @@
+-- original file : url.lua
+-- for more into : see util-soc.lua
+
+local tonumber, tostring, type = tonumber, tostring, type
+
+local gsub, sub, match, find, format, byte, char = string.gsub, string.sub, string.match, string.find, string.format, string.byte, string.char
+local insert = table.insert
+
+local socket = socket or require("socket")
+
+local url = {
+ _VERSION = "URL 1.0.3",
+}
+
+socket.url = url
+
+function url.escape(s)
+ return (gsub(s, "([^A-Za-z0-9_])", function(c)
+ return format("%%%02x", byte(c))
+ end))
+end
+
+local function make_set(t) -- table.tohash
+ local s = { }
+ for i=1,#t do
+ s[t[i]] = true
+ end
+ return s
+end
+
+local segment_set = make_set {
+ "-", "_", ".", "!", "~", "*", "'", "(",
+ ")", ":", "@", "&", "=", "+", "$", ",",
+}
+
+local function protect_segment(s)
+ return gsub(s, "([^A-Za-z0-9_])", function(c)
+ if segment_set[c] then
+ return c
+ else
+ return format("%%%02X", byte(c))
+ end
+ end)
+end
+
+function url.unescape(s)
+ return (gsub(s, "%%(%x%x)", function(hex)
+ return char(tonumber(hex,16))
+ end))
+end
+
+local function absolute_path(base_path, relative_path)
+ if find(relative_path,"^/") then
+ return relative_path
+ end
+ local path = gsub(base_path, "[^/]*$", "")
+ path = path .. relative_path
+ path = gsub(path, "([^/]*%./)", function (s)
+ if s ~= "./" then
+ return s
+ else
+ return ""
+ end
+ end)
+ path = gsub(path, "/%.$", "/")
+ local reduced
+ while reduced ~= path do
+ reduced = path
+ path = gsub(reduced, "([^/]*/%.%./)", function (s)
+ if s ~= "../../" then
+ return ""
+ else
+ return s
+ end
+ end)
+ end
+ path = gsub(reduced, "([^/]*/%.%.)$", function (s)
+ if s ~= "../.." then
+ return ""
+ else
+ return s
+ end
+ end)
+ return path
+end
+
+function url.parse(url, default)
+ local parsed = { }
+ for k, v in next, default or parsed do
+ parsed[k] = v
+ end
+ if not url or url == "" then
+ return nil, "invalid url"
+ end
+ url = gsub(url, "#(.*)$", function(f)
+ parsed.fragment = f
+ return ""
+ end)
+ url = gsub(url, "^([%w][%w%+%-%.]*)%:", function(s)
+ parsed.scheme = s
+ return ""
+ end)
+ url = gsub(url, "^//([^/]*)", function(n)
+ parsed.authority = n
+ return ""
+ end)
+ url = gsub(url, "%?(.*)", function(q)
+ parsed.query = q
+ return ""
+ end)
+ url = gsub(url, "%;(.*)", function(p)
+ parsed.params = p
+ return ""
+ end)
+ if url ~= "" then
+ parsed.path = url
+ end
+ local authority = parsed.authority
+ if not authority then
+ return parsed
+ end
+ authority = gsub(authority,"^([^@]*)@", function(u)
+ parsed.userinfo = u
+ return ""
+ end)
+ authority = gsub(authority, ":([^:%]]*)$", function(p)
+ parsed.port = p
+ return ""
+ end)
+ if authority ~= "" then
+ parsed.host = match(authority, "^%[(.+)%]$") or authority
+ end
+ local userinfo = parsed.userinfo
+ if not userinfo then
+ return parsed
+ end
+ userinfo = gsub(userinfo, ":([^:]*)$", function(p)
+ parsed.password = p
+ return ""
+ end)
+ parsed.user = userinfo
+ return parsed
+end
+
+function url.build(parsed)
+ local url = parsed.path or ""
+ if parsed.params then
+ url = url .. ";" .. parsed.params
+ end
+ if parsed.query then
+ url = url .. "?" .. parsed.query
+ end
+ local authority = parsed.authority
+ if parsed.host then
+ authority = parsed.host
+ if find(authority, ":") then -- IPv6?
+ authority = "[" .. authority .. "]"
+ end
+ if parsed.port then
+ authority = authority .. ":" .. tostring(parsed.port)
+ end
+ local userinfo = parsed.userinfo
+ if parsed.user then
+ userinfo = parsed.user
+ if parsed.password then
+ userinfo = userinfo .. ":" .. parsed.password
+ end
+ end
+ if userinfo then authority = userinfo .. "@" .. authority end
+ end
+ if authority then
+ url = "//" .. authority .. url
+ end
+ if parsed.scheme then
+ url = parsed.scheme .. ":" .. url
+ end
+ if parsed.fragment then
+ url = url .. "#" .. parsed.fragment
+ end
+ return url
+end
+
+function url.absolute(base_url, relative_url)
+ local base_parsed
+ if type(base_url) == "table" then
+ base_parsed = base_url
+ base_url = url.build(base_parsed)
+ else
+ base_parsed = url.parse(base_url)
+ end
+ local relative_parsed = url.parse(relative_url)
+ if not base_parsed then
+ return relative_url
+ elseif not relative_parsed then
+ return base_url
+ elseif relative_parsed.scheme then
+ return relative_url
+ else
+ relative_parsed.scheme = base_parsed.scheme
+ if not relative_parsed.authority then
+ relative_parsed.authority = base_parsed.authority
+ if not relative_parsed.path then
+ relative_parsed.path = base_parsed.path
+ if not relative_parsed.params then
+ relative_parsed.params = base_parsed.params
+ if not relative_parsed.query then
+ relative_parsed.query = base_parsed.query
+ end
+ end
+ else
+ relative_parsed.path = absolute_path(base_parsed.path or "", relative_parsed.path)
+ end
+ end
+ return url.build(relative_parsed)
+ end
+end
+
+function url.parse_path(path)
+ local parsed = { }
+ path = path or ""
+ gsub(path, "([^/]+)", function (s)
+ insert(parsed, s)
+ end)
+ for i=1,#parsed do
+ parsed[i] = url.unescape(parsed[i])
+ end
+ if sub(path, 1, 1) == "/" then
+ parsed.is_absolute = 1
+ end
+ if sub(path, -1, -1) == "/" then
+ parsed.is_directory = 1
+ end
+ return parsed
+end
+
+function url.build_path(parsed, unsafe)
+ local path = ""
+ local n = #parsed
+ if unsafe then
+ for i = 1, n-1 do
+ path = path .. parsed[i] .. "/"
+ end
+ if n > 0 then
+ path = path .. parsed[n]
+ if parsed.is_directory then
+ path = path .. "/"
+ end
+ end
+ else
+ for i = 1, n-1 do
+ path = path .. protect_segment(parsed[i]) .. "/"
+ end
+ if n > 0 then
+ path = path .. protect_segment(parsed[n])
+ if parsed.is_directory then
+ path = path .. "/"
+ end
+ end
+ end
+ if parsed.is_absolute then
+ path = "/" .. path
+ end
+ return path
+end
+
+package.loaded["socket.url"] = url
+
+return url
diff --git a/tex/context/base/mkiv/util-soc.lua b/tex/context/base/mkiv/util-soc.lua
index 3a52ee86d..590287a25 100644
--- a/tex/context/base/mkiv/util-soc.lua
+++ b/tex/context/base/mkiv/util-soc.lua
@@ -6,6 +6,29 @@ if not modules then modules = { } end modules ['util-soc'] = {
license = "see context related readme files"
}
+--[[--
+
+In LuaTeX we provide the socket library that is more or less the standard one for
+Lua. It has been around for a while and seems to be pretty stable. The binary
+module is copmpiled into LuaTeX and the accompanying .lua files are preloaded.
+These files are mostly written by Diego Nehab, Andre Carregal, Javier Guerra, and
+Fabio Mascarenhas with contributions from Diego Nehab, Mike Pall, David Burgess,
+Leonardo Godinho, Thomas Harning Jr., and Gary NG. The originals are part of and
+copyrighted by the Kepler project.
+
+Here we reload a slightly reworked version of these .lua files. We keep the same
+(documented) interface but streamlined some fo the code. No more modules, no more
+pre 5.2 Lua, etc. Also, as it loads into the ConTeXt ecosystem, we plug in some
+logging. (and maybe tracing in the future). As we don't support serial ports in
+LuaTeX, related code has been dropped.
+
+The files are reformatted so that we can more easilly add additional features
+and/or tracing options. Any error introduced there is our fault! The url module
+might be replaced by the one in ConTeXt. When we need mbox a suitable variant
+will be provided.
+
+--]]--
+
local format = string.format
local smtp = require("socket.smtp")
@@ -95,3 +118,12 @@ function mail.send(specification)
return true
end
end
+
+-- for now we have this here:
+
+if socket then
+
+ math.initialseed = tonumber(string.sub(string.reverse(tostring(math.ceil(socket.gettime()*10000))),1,6))
+ math.randomseed(math.initialseed)
+
+end
diff --git a/tex/context/base/mkiv/util-sql-imp-ffi.lua b/tex/context/base/mkiv/util-sql-imp-ffi.lua
index 2a2bc6569..3731933f1 100644
--- a/tex/context/base/mkiv/util-sql-imp-ffi.lua
+++ b/tex/context/base/mkiv/util-sql-imp-ffi.lua
@@ -8,7 +8,7 @@ if not modules then modules = { } end modules ['util-sql-imp-ffi'] = {
-- I looked at luajit-mysql to see how the ffi mapping was done but it didn't work
-- out that well (at least not on windows) but I got the picture. As I have somewhat
--- different demands I simplified / redid the ffi bti and just took the swiglib
+-- different demands I simplified / redid the ffi bit and just took the swiglib
-- variant and adapted that.
local tonumber = tonumber
@@ -17,6 +17,7 @@ local format, byte = string.format, string.byte
local lpegmatch = lpeg.match
local setmetatable, type = setmetatable, type
local sleep = os.sleep
+local formatters = string.formatters
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)
@@ -33,6 +34,9 @@ ffi.cdef [[
a query. The rest is handled already in the Lua code elsewhere.
*/
+ void free(void*ptr);
+ void * malloc(size_t size);
+
typedef void MYSQL_instance;
typedef void MYSQL_result;
typedef char **MYSQL_row;
@@ -115,6 +119,14 @@ ffi.cdef [[
MYSQL_result *result
);
+ unsigned int mysql_affected_rows (
+ MYSQL_instance *mysql
+ );
+
+ unsigned int mysql_field_count (
+ MYSQL_instance *mysql
+ );
+
unsigned int mysql_num_fields (
MYSQL_result *res
);
@@ -163,12 +175,14 @@ local dataprepared = helpers.preparetemplate
local serialize = sql.serialize
local deserialize = sql.deserialize
-local mysql_initialize = mysql.mysql_init
+local mysql_open_session = 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_affected_rows = mysql.mysql_affected_rows
+local mysql_field_count = mysql.mysql_field_count
local mysql_field_seek = mysql.mysql_field_seek
local mysql_num_fields = mysql.mysql_num_fields
local mysql_fetch_fields = mysql.mysql_fetch_fields
@@ -180,6 +194,7 @@ local mysql_init = mysql.mysql_init
local mysql_store_result = mysql.mysql_store_result
local mysql_free_result = mysql.mysql_free_result
+local mysql_error_number = mysql.mysql_errno
local mysql_error_message = mysql.mysql_error
local NULL = ffi.cast("MYSQL_result *",0)
@@ -187,325 +202,361 @@ local NULL = ffi.cast("MYSQL_result *",0)
local ffi_tostring = ffi.string
local ffi_gc = ffi.gc
------ mysqldata = ffi.cast("MYSQL_instance*",mysql.malloc(1024*1024))
-local instance = mysql.mysql_init(nil) -- (mysqldata)
+local instance = mysql.mysql_init(nil)
local mysql_constant_false = false
local mysql_constant_true = true
-local function finish(t)
- local r = t._result_
- if r then
- ffi_gc(r,mysql_free_result)
+local wrapresult do
+
+ local function collect(t)
+ local result = t._result_
+ if result then
+ ffi_gc(result,mysql_free_result)
+ end
end
-end
-local function getcolnames(t)
- return t.names
-end
+ local function finish(t)
+ local result = t._result_
+ if result then
+ t._result_ = nil
+ ffi_gc(result,mysql_free_result)
+ end
+ end
-local function getcoltypes(t)
- return t.types
-end
+ local function getcoldata(t)
+ local result = t._result_
+ local nofrows = t.nofrows
+ local noffields = t.noffields
+ local names = { }
+ local types = { }
+ local fields = mysql_fetch_fields(result)
+ for i=1,noffields do
+ local field = fields[i-1]
+ names[i] = ffi_tostring(field.name)
+ types[i] = tonumber(field.type) -- todo
+ end
+ t.names = names
+ t.types = types
+ end
-local function numrows(t)
- return tonumber(t.nofrows)
-end
+ local function getcolnames(t)
+ local names = t.names
+ if names then
+ return names
+ end
+ getcoldata(t)
+ return t.names
+ end
-local function list(t)
- local result = t._result_
- if result then
- local row = mysql_fetch_row(result)
- -- local len = mysql_fetch_lengths(result)
- local result = { }
- for i=1,t.noffields do
- result[i] = ffi_tostring(row[i-1])
+ local function getcoltypes(t)
+ local types = t.types
+ if types then
+ return types
end
- return result
+ getcoldata(t)
+ return t.types
end
-end
-local function hash(t)
- local result = t._result_
- local fields = t.names
- if result then
- local row = mysql_fetch_row(result)
- -- local len = mysql_fetch_lengths(result)
- local result = { }
- for i=1,t.noffields do
- result[fields[i]] = ffi_tostring(row[i-1])
+ local function numrows(t)
+ return t.nofrows
+ end
+
+ -- local function fetch(t)
+ -- local
+ -- local row = mysql_fetch_row(result)
+ -- local result = { }
+ -- for i=1,t.noffields do
+ -- result[i] = ffi_tostring(row[i-1])
+ -- end
+ -- return unpack(result)
+ -- end
+
+ local mt = {
+ __gc = collect,
+ __index = {
+ _result_ = nil,
+ close = finish,
+ numrows = numrows,
+ getcolnames = getcolnames,
+ getcoltypes = getcoltypes,
+ -- fetch = fetch, -- not efficient
+ }
+ }
+
+ wrapresult = function(connection)
+ local result = mysql_store_result(connection)
+ if result ~= NULL then
+ mysql_field_seek(result,0)
+ local t = {
+ _result_ = result,
+ nofrows = tonumber(mysql_num_rows (result) or 0) or 0,
+ noffields = tonumber(mysql_num_fields(result) or 0) or 0,
+ }
+ return setmetatable(t,mt)
+ elseif tonumber(mysql_field_count(connection) or 0) or 0 > 0 then
+ return tonumber(mysql_affected_rows(connection))
end
- return result
end
-end
-local function wholelist(t)
- return 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,
- -- fallback
- _result_ = nil,
- names = { },
- types = { },
- noffields = 0,
- nofrows = 0,
- }
-}
+local initializesession do
-local nt = setmetatable({},mt)
+ -- timeouts = [ connect_timeout |wait_timeout | interactive_timeout ]
--- session
+ local timeout -- = 3600 -- to be tested
-local function close(t)
- mysql_close_connection(t._connection_)
-end
+ -- connection
-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)
- if result ~= NULL then
- mysql_field_seek(result,0)
- local nofrows = tonumber(mysql_num_rows(result) or 0)
- local noffields = tonumber(mysql_num_fields(result))
- local names = { }
- local types = { }
- local fields = mysql_fetch_fields(result)
- for i=1,noffields do
- local field = fields[i-1]
- names[i] = ffi_tostring(field.name)
- types[i] = tonumber(field.type) -- todo
- end
- local t = {
- _result_ = result,
- names = names,
- types = types,
- noffields = noffields,
- nofrows = nofrows,
- }
- return setmetatable(t,mt)
+ local function close(t)
+ -- just a struct ?
+ 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
+ return wrapresult(connection)
else
- return nt
+ -- mysql_error_number(connection)
+ return false, ffi_tostring(mysql_error_message(connection))
end
end
+ return false
end
- return false
-end
-local mt = { __index = {
- close = close,
- execute = execute,
+ 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,
- NULL,
- 0
- )
- if connection ~= NULL then
- local t = {
- _connection_ = connection,
- }
- return setmetatable(t,mt)
+ -- session
+
+ 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,
+ NULL,
+ 0
+ )
+ if connection ~= NULL then
+ if timeout then
+ execute(connection,formatters["SET SESSION connect_timeout=%s ;"](timeout))
+ end
+ local t = {
+ _connection_ = connection,
+ }
+ return setmetatable(t,mt)
+ end
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 function message(t)
+ return mysql_error_message(t._session_)
+ end
-local mt = {
- __index = {
- connect = open,
- close = close,
- message = message,
- }
-}
+ local function close(t)
+ local connection = t._connection_
+ if connection and connection ~= NULL then
+ ffi_gc(connection, mysql_close)
+ t.connection = nil
+ end
+ end
-local function initialize()
- local session = {
- _session_ = mysql_initialize(instance) -- maybe share, single thread anyway
+ local mt = {
+ __index = {
+ connect = open,
+ close = close,
+ message = message,
+ },
}
- return setmetatable(session,mt)
-end
--- -- -- --
+ initializesession = function()
+ local session = {
+ _session_ = mysql_open_session(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 error_in_connection(specification,action)
- report_state("error in connection: [%s] user %s into %s at %s:%s",
- action or "unknown",
- specification.username or "no username",
- specification.database or "no database",
- specification.host or "no host",
- specification.port or "no port"
- )
-end
+local executequery do
-local function datafetched(specification,query,converter)
- if not query or query == "" then
- report_state("no valid query")
- return { }, { }
+ local function connect(session,specification)
+ return session:connect(
+ specification.database or "",
+ specification.username or "",
+ specification.password or "",
+ specification.host or "",
+ specification.port
+ )
end
- local id = specification.id
- local session, connection
- if id then
- local c = cache[id]
- if c then
- session = c.session
- connection = c.connection
+
+ local function fetched(specification,query,converter)
+ if not query or query == "" then
+ report_state("no valid query")
+ return false
end
- if not connection then
- session = initialize()
- connection = connect(session,specification)
+ 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
- for i=1,nofretries do
- sleep(retrydelay)
- report_state("retrying to connect: [%s.%s] %s@%s to %s:%s",
- id,i,
- specification.database or "no database",
- specification.username or "no username",
- specification.host or "no host",
- specification.port or "no port"
- )
- connection = connect(session,specification)
- if connection then
- break
- end
+ session = initializesession()
+ if not session then
+ return formatters["no session for %a"](id)
end
- end
- if connection then
- cache[id] = { session = session, connection = connection }
- end
- end
- else
- session = initialize()
- connection = connect(session,specification)
- if not connection then
- for i=1,nofretries do
- sleep(retrydelay)
- report_state("retrying to connect: [%s] %s@%s to %s:%s",
- i,
- specification.database or "no database",
- specification.username or "no username",
- specification.host or "no host",
- specification.port or "no port"
- )
connection = connect(session,specification)
- if connection then
- break
+ if not connection then
+ return formatters["no connection for %a"](id)
end
+ cache[id] = { session = session, connection = connection }
+ end
+ else
+ session = initializesession()
+ if not session then
+ return "no session"
+ end
+ connection = connect(session,specification)
+ if not connection then
+ return "no connection"
end
end
- end
- if not connection then
- report_state("error in connection: %s@%s to %s:%s",
+ 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 or "?"))
- message = message and format("%s\n%s",message,m) or m
+ return "no connection"
end
- if type(r) == "table" then
- result = r
- okay = true
- elseif not m then
- okay = true
+ query = lpegmatch(querysplitter,query)
+ local result, okay
+ for i=1,#query do
+ local q = query[i]
+ local r, m = connection:execute(q)
+ if m then
+ report_state("error in query to host %a: %s",specification.host,string.collapsespaces(q or "?"))
+ if m then
+ report_state("message: %s",m)
+ end
+ end
+ local t = type(r)
+ if t == "table" then
+ result = r
+ okay = true
+ elseif t == "number" then
+ okay = true
+ end
end
- end
- local data, keys
- if result then
- if converter then
- data = converter.ffi(result)
- else
- keys = result.names
- data = { }
- for i=1,result.nofrows do
- data[i] = result:hash()
+ if not okay then -- can go
+ -- why do we close a session
+ if connection then
+ connection:close()
+ end
+ if session then
+ session:close()
end
+ if id then
+ cache[id] = nil
+ end
+ return "execution error"
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()
+ local data, keys
+ if result then
+ if converter then
+ data = converter.ffi(result)
+ else
+ local _result_ = result._result_
+ local noffields = result.noffields
+ local nofrows = result.nofrows
+ keys = result:getcolnames()
+ data = { }
+ if noffields > 0 and nofrows > 0 then
+ for i=1,nofrows do
+ local cells = { }
+ local row = mysql_fetch_row(_result_)
+ for j=1,noffields do
+ local s = row[j-1]
+ local k = keys[j]
+ if s == NULL then
+ cells[k] = ""
+ else
+ cells[k] = ffi_tostring(s)
+ end
+ end
+ data[i] = cells
+ end
+ end
+ end
+ result:close()
+ end
+ --
+ if not id then
+ if connection then
+ connection:close()
+ end
+ if session then
+ session:close()
+ end
+ end
+ return false, data, keys
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
+ local function datafetched(specification,query,converter)
+ local callokay, connectionerror, data, keys = pcall(fetched,specification,query,converter)
+ if not callokay then
+ report_state("call error, retrying")
+ callokay, connectionerror, data, keys = pcall(fetched,specification,query,converter)
+ elseif connectionerror then
+ report_state("error: %s, retrying",connectionerror)
+ callokay, connectionerror, data, keys = pcall(fetched,specification,query,converter)
+ end
+ if not callokay then
+ report_state("persistent call error")
+ elseif connectionerror then
+ report_state("persistent error: %s",connectionerror)
+ end
+ return data or { }, keys or { }
end
- local one = data[1]
- if one then
- setmetatable(data,{ __index = one } )
+
+ executequery = function(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
- return data, keys
+
end
local wraptemplate = [[
@@ -530,13 +581,14 @@ return function(result)
if not result then
return { }
end
- local nofrows = result.nofrows or 0
+ local nofrows = result.nofrows
if nofrows == 0 then
return { }
end
- local noffields = result.noffields or 0
- local _result_ = result._result_
+ local noffields = result.noffields
local target = { } -- no %s needed here
+ local _result_ = result._result_
+ -- we can share cells
for i=1,nofrows do
local cells = { }
local row = mysql_fetch_row(_result_)
@@ -552,7 +604,7 @@ return function(result)
%s
}
end
- result:finish() -- result:close()
+ result:close()
return target
end
]]
@@ -560,9 +612,9 @@ end
local celltemplate = "cells[%s]"
methods.ffi = {
- runner = function() end, -- never called
- execute = execute,
- initialize = initialize, -- returns session
+ runner = function() end, -- never called
+ execute = executequery,
+ initialize = initializesession, -- returns session
usesfiles = false,
wraptemplate = wraptemplate,
celltemplate = celltemplate,
diff --git a/tex/context/base/mkiv/util-sql-imp-library.lua b/tex/context/base/mkiv/util-sql-imp-library.lua
index a2b692e45..dbbeb32cc 100644
--- a/tex/context/base/mkiv/util-sql-imp-library.lua
+++ b/tex/context/base/mkiv/util-sql-imp-library.lua
@@ -156,13 +156,13 @@ local function fetched(specification,query,converter)
okay = true
end
end
- if not okay then -- can go
- if session then
- session:close()
- end
+ if not okay then
if connection then
connection:close()
end
+ if session then
+ session:close()
+ end
if id then
cache[id] = nil
end
diff --git a/tex/context/base/mkiv/util-sql-imp-sqlite.lua b/tex/context/base/mkiv/util-sql-imp-sqlite.lua
index 04d5ced3a..cf4a3a8b0 100644
--- a/tex/context/base/mkiv/util-sql-imp-sqlite.lua
+++ b/tex/context/base/mkiv/util-sql-imp-sqlite.lua
@@ -132,7 +132,6 @@ setmetatable(cache, {
local f_preamble = formatters[ [[
ATTACH `%s` AS `%s` ;
PRAGMA `%s`.synchronous = normal ;
-PRAGMA journal_mode = truncate ;
]] ]
local function execute(specification)
@@ -211,17 +210,19 @@ local function execute(specification)
else
local column = { }
callback = function(data,nofcolumns,values,fields)
- for i=0,nofcolumns-1 do
+ for i=1,nofcolumns do
local field
if keysdone then
- field = keys[i+1]
+ field = keys[i]
else
-- field = get_list_item(fields,i)
- field = ffi_tostring(fields[i])
+ field = ffi_tostring(fields[i-1])
keys[i+1] = field
end
- -- column[field] = get_list_item(values,i)
- column[field] = ffi_tostring(values[i])
+ if field then
+ -- column[field] = get_list_item(values,i)
+ column[field] = ffi_tostring(values[i-1])
+ end
end
nofrows = nofrows + 1
keysdone = true
diff --git a/tex/context/base/mkiv/util-sql-logins.lua b/tex/context/base/mkiv/util-sql-logins.lua
index dcb48fb35..c19bfbdf8 100644
--- a/tex/context/base/mkiv/util-sql-logins.lua
+++ b/tex/context/base/mkiv/util-sql-logins.lua
@@ -211,9 +211,10 @@ end
logins.userpurge = userpurge
local function verdict(okay,...)
- if not trace_logins then
- -- no tracing
- elseif okay then
+-- if not trace_logins then
+-- -- no tracing
+-- else
+ if okay then
report_logins("%s, granted",formatter(...))
else
report_logins("%s, blocked",formatter(...))
@@ -244,6 +245,11 @@ function logins.userpermitted(db,name)
}
end
if not data or not data.name then
+ if not data then
+ report_logins("no user data for %a",name)
+ else
+ report_logins("no name entry for %a",name)
+ end
local d = {
name = name,
state = 0,
diff --git a/tex/context/base/mkiv/util-sql-users.lua b/tex/context/base/mkiv/util-sql-users.lua
index 7204fb310..57c99b2a7 100644
--- a/tex/context/base/mkiv/util-sql-users.lua
+++ b/tex/context/base/mkiv/util-sql-users.lua
@@ -25,12 +25,16 @@ local trace_sql = false trackers.register("sql.users.trace", function(v) trace_
local report = logs.reporter("sql","users")
local split = lpeg.splitat(":")
+
local valid = nil
local hash = function(s) return "MD5:" .. sumHEXA(s) end
+local sha2 = sha2 or (utilities and utilities.sha2)
-if LUAVERSION >= 5.3 then
+if not sha2 and LUAVERSION >= 5.3 then
+ sha2 = require("util-sha")
+end
- local sha2 = require("util-sha")
+if sha2 then
local HASH224 = sha2.HASH224
local HASH256 = sha2.HASH256
@@ -238,9 +242,7 @@ function users.valid(db,username,password,address)
name = username,
},
}
-
local data = data and data[1]
-
if not data then
return false, "unknown user"
elseif not data.enabled then
diff --git a/tex/context/base/mkiv/util-sta.lua b/tex/context/base/mkiv/util-sta.lua
index d140cacdc..7819395f6 100644
--- a/tex/context/base/mkiv/util-sta.lua
+++ b/tex/context/base/mkiv/util-sta.lua
@@ -289,24 +289,24 @@ end
--
-- local concat = table.concat
--
--- local pdfpageliteral = nodes.pool.pdfpageliteral
+-- local pageliteral = nodes.pool.pageliteral
--
-- function demostacker.start(s,t,first,last)
-- local n = whatever[t[last]]
-- -- s.report("start: %s",n)
--- return pdfpageliteral(n)
+-- return pageliteral(n)
-- end
--
-- function demostacker.stop(s,t,first,last)
-- local n = whatever[false]
-- -- s.report("stop: %s",n)
--- return pdfpageliteral(n)
+-- return pageliteral(n)
-- end
--
-- function demostacker.change(s,t1,first1,last1,t2,first2,last2)
-- local n = whatever[t2[last2]]
-- -- s.report("change: %s",n)
--- return pdfpageliteral(n)
+-- return pageliteral(n)
-- end
--
-- demostacker.mode = "switch"
@@ -325,7 +325,7 @@ end
-- r[#r+1] = whatever[t[i]]
-- end
-- -- s.report("start: %s",concat(r," "))
--- return pdfpageliteral(concat(r," "))
+-- return pageliteral(concat(r," "))
-- end
--
-- function demostacker.stop(s,t,first,last)
@@ -334,7 +334,7 @@ end
-- r[#r+1] = whatever[false]
-- end
-- -- s.report("stop: %s",concat(r," "))
--- return pdfpageliteral(concat(r," "))
+-- return pageliteral(concat(r," "))
-- end
--
-- function demostacker.change(s,t1,first1,last1,t2,first2,last2)
@@ -346,7 +346,7 @@ end
-- r[#r+1] = whatever[t2[i]]
-- end
-- -- s.report("change: %s",concat(r," "))
--- return pdfpageliteral(concat(r," "))
+-- return pageliteral(concat(r," "))
-- end
--
-- demostacker.mode = "stack"
diff --git a/tex/context/base/mkiv/util-sto.lua b/tex/context/base/mkiv/util-sto.lua
index 5b6915eaf..a08d25ced 100644
--- a/tex/context/base/mkiv/util-sto.lua
+++ b/tex/context/base/mkiv/util-sto.lua
@@ -196,6 +196,19 @@ function table.getmetatablekey(t,key,value)
return m and m[key]
end
+function table.makeweak(t)
+ if not t then
+ t = { }
+ end
+ local m = getmetatable(t)
+ if m then
+ m.__mode = "v"
+ else
+ setmetatable(t,{ __mode = "v" })
+ end
+ return t
+end
+
-- Problem: we have no __next (which is ok as it would probably slow down lua) so
-- we cannot loop over the keys.
diff --git a/tex/context/base/mkiv/util-str.lua b/tex/context/base/mkiv/util-str.lua
index 05ff9f304..713c294eb 100644
--- a/tex/context/base/mkiv/util-str.lua
+++ b/tex/context/base/mkiv/util-str.lua
@@ -22,46 +22,72 @@ local utfchar, utfbyte, utflen = utf.char, utf.byte, utf.len
----- loadstripped = utilities.lua.loadstripped
----- setmetatableindex = table.setmetatableindex
-local loadstripped = nil
-local oldfashioned = LUAVERSION < 5.2
-
-if oldfashioned then
-
- loadstripped = function(str,shortcuts)
- return load(str)
- end
-
-else
-
- loadstripped = function(str,shortcuts)
- if shortcuts then
- return load(dump(load(str),true),nil,nil,shortcuts)
- else
- return load(dump(load(str),true))
- end
+local loadstripped = function(str,shortcuts)
+ if shortcuts then
+ return load(dump(load(str),true),nil,nil,shortcuts)
+ else
+ return load(dump(load(str),true))
end
-
end
-- todo: make a special namespace for the formatter
if not number then number = { } end -- temp hack for luatex-fonts
-local stripper = patterns.stripzeros
+local stripzero = patterns.stripzero
+local stripzeros = patterns.stripzeros
local newline = patterns.newline
local endofstring = patterns.endofstring
+local anything = patterns.anything
local whitespace = patterns.whitespace
+local space = patterns.space
local spacer = patterns.spacer
local spaceortab = patterns.spaceortab
+local digit = patterns.digit
+local sign = patterns.sign
+local period = patterns.period
+
+-- local function points(n)
+-- n = tonumber(n)
+-- return (not n or n == 0) and "0pt" or lpegmatch(stripzeros,format("%.5fpt",n/65536))
+-- end
+
+-- local function basepoints(n)
+-- n = tonumber(n)
+-- return (not n or n == 0) and "0bp" or lpegmatch(stripzeros,format("%.5fbp", n*(7200/7227)/65536))
+-- end
+
+local ptf = 1 / 65536
+local bpf = (7200/7227) / 65536
local function points(n)
+ if n == 0 then
+ return "0pt"
+ end
n = tonumber(n)
- return (not n or n == 0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536))
+ if not n or n == 0 then
+ return "0pt"
+ end
+ n = n * ptf
+ if n % 1 == 0 then
+ return format("%ipt",n)
+ end
+ return lpegmatch(stripzeros,format("%.5fpt",n)) -- plural as we need to keep the pt
end
local function basepoints(n)
+ if n == 0 then
+ return "0pt"
+ end
n = tonumber(n)
- return (not n or n == 0) and "0bp" or lpegmatch(stripper,format("%.5fbp", n*(7200/7227)/65536))
+ if not n or n == 0 then
+ return "0pt"
+ end
+ n = n * bpf
+ if n % 1 == 0 then
+ return format("%ibp",n)
+ end
+ return lpegmatch(stripzeros,format("%.5fbp",n)) -- plural as we need to keep the pt
end
number.points = points
@@ -72,7 +98,6 @@ number.basepoints = basepoints
local rubish = spaceortab^0 * newline
local anyrubish = spaceortab + newline
-local anything = patterns.anything
local stripped = (spaceortab^1 / "") * newline
local leading = rubish^0 / ""
local trailing = (anyrubish^1 * endofstring) / ""
@@ -140,7 +165,7 @@ local pattern =
+ newline * Cp() / function(position)
extra, start = 0, position
end
- + patterns.anything
+ + anything
)^1)
function strings.tabtospace(str,tab)
@@ -183,27 +208,31 @@ end
-- return str
-- end
-local space = spacer^0
-local nospace = space/""
-local endofline = nospace * newline
+local optionalspace = spacer^0
+local nospace = optionalspace/""
+local endofline = nospace * newline
-local stripend = (whitespace^1 * endofstring)/""
+local stripend = (whitespace^1 * endofstring)/""
-local normalline = (nospace * ((1-space*(newline+endofstring))^1) * nospace)
+local normalline = (nospace * ((1-optionalspace*(newline+endofstring))^1) * nospace)
-local stripempty = endofline^1/""
-local normalempty = endofline^1
-local singleempty = endofline * (endofline^0/"")
-local doubleempty = endofline * endofline^-1 * (endofline^0/"")
+local stripempty = endofline^1/""
+local normalempty = endofline^1
+local singleempty = endofline * (endofline^0/"")
+local doubleempty = endofline * endofline^-1 * (endofline^0/"")
+local stripstart = stripempty^0
-local stripstart = stripempty^0
+local intospace = whitespace^1/" "
+local noleading = whitespace^1/""
+local notrailing = noleading * endofstring
-local p_prune_normal = Cs ( stripstart * ( stripend + normalline + normalempty )^0 )
-local p_prune_collapse = Cs ( stripstart * ( stripend + normalline + doubleempty )^0 )
-local p_prune_noempty = Cs ( stripstart * ( stripend + normalline + singleempty )^0 )
-local p_retain_normal = Cs ( ( normalline + normalempty )^0 )
-local p_retain_collapse = Cs ( ( normalline + doubleempty )^0 )
-local p_retain_noempty = Cs ( ( normalline + singleempty )^0 )
+local p_prune_normal = Cs ( stripstart * ( stripend + normalline + normalempty )^0 )
+local p_prune_collapse = Cs ( stripstart * ( stripend + normalline + doubleempty )^0 )
+local p_prune_noempty = Cs ( stripstart * ( stripend + normalline + singleempty )^0 )
+local p_prune_intospace = Cs ( noleading * ( notrailing + intospace + 1 )^0 )
+local p_retain_normal = Cs ( ( normalline + normalempty )^0 )
+local p_retain_collapse = Cs ( ( normalline + doubleempty )^0 )
+local p_retain_noempty = Cs ( ( normalline + singleempty )^0 )
-- function striplines(str,prune,collapse,noempty)
-- if prune then
@@ -229,10 +258,11 @@ local striplinepatterns = {
["prune"] = p_prune_normal,
["prune and collapse"] = p_prune_collapse, -- default
["prune and no empty"] = p_prune_noempty,
+ ["prune and to space"] = p_prune_intospace,
["retain"] = p_retain_normal,
["retain and collapse"] = p_retain_collapse,
["retain and no empty"] = p_retain_noempty,
- ["collapse"] = patterns.collapser, -- how about: stripper fullstripper
+ ["collapse"] = patterns.collapser,
}
setmetatable(striplinepatterns,{ __index = function(t,k) return p_prune_collapse end })
@@ -243,6 +273,10 @@ function strings.striplines(str,how)
return str and lpegmatch(striplinepatterns[how],str) or str
end
+function strings.collapse(str) -- maybe also in strings
+ return str and lpegmatch(p_prune_intospace,str) or str
+end
+
-- also see: string.collapsespaces
strings.striplong = strings.striplines -- for old times sake
@@ -258,13 +292,14 @@ strings.striplong = strings.striplines -- for old times sake
-- " zus wim jet",
-- " ",
-- }, "\n")
-
+--
-- local str = table.concat( {
-- " aaaa",
-- " bb",
-- " cccccc",
+-- " ",
-- }, "\n")
-
+--
-- for k, v in table.sortedhash(utilities.strings.striplinepatterns) do
-- logs.report("stripper","method: %s, result: [[%s]]",k,utilities.strings.striplines(str,k))
-- end
@@ -335,6 +370,7 @@ end
-- automatic %...a 'whatever' (string, table, ...)
-- automatic %...A "whatever" (string, table, ...)
-- zap %...z skip
+-- stripped %...N %...N
-- comma/period real %...m
-- period/comma real %...M
-- formatted float %...k n.m
@@ -410,27 +446,45 @@ end
-- maybe to util-num
-local digit = patterns.digit
-local period = patterns.period
-local three = digit * digit * digit
+local two = digit * digit
+local three = two * digit
+local prefix = (Carg(1) * three)^1
local splitter = Cs (
- (((1 - (three^1 * period))^1 + C(three)) * (Carg(1) * three)^1 + C((1-period)^1))
- * (P(1)/"" * Carg(2)) * C(2)
+ (((1 - (three^1 * period))^1 + C(three)) * prefix + C((1-period)^1))
+ * (anything/"" * Carg(2)) * C(2)
+)
+
+local splitter3 = Cs (
+ three * prefix * endofstring +
+ two * prefix * endofstring +
+ digit * prefix * endofstring +
+ three +
+ two +
+ digit
)
patterns.formattednumber = splitter
function number.formatted(n,sep1,sep2)
- local s = type(s) == "string" and n or format("%0.2f",n)
- if sep1 == true then
- return lpegmatch(splitter,s,1,".",",")
- elseif sep1 == "." then
- return lpegmatch(splitter,s,1,sep1,sep2 or ",")
- elseif sep1 == "," then
- return lpegmatch(splitter,s,1,sep1,sep2 or ".")
+ if sep1 == false then
+ if type(n) == "number" then
+ n = tostring(n)
+ end
+ return lpegmatch(splitter3,n,1,sep2 or ".")
else
- return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".")
+ if type(n) == "number" then
+ n = format("%0.2f",n)
+ end
+ if sep1 == true then
+ return lpegmatch(splitter,n,1,".",",")
+ elseif sep1 == "." then
+ return lpegmatch(splitter,n,1,sep1,sep2 or ",")
+ elseif sep1 == "," then
+ return lpegmatch(splitter,n,1,sep1,sep2 or ".")
+ else
+ return lpegmatch(splitter,n,1,sep1 or ",",sep2 or ".")
+ end
end
end
@@ -443,14 +497,22 @@ end
-- print(number.formatted(1234567))
-- print(number.formatted(12345678))
-- print(number.formatted(12345678,true))
+-- print(number.formatted(1,false))
+-- print(number.formatted(12,false))
+-- print(number.formatted(123,false))
+-- print(number.formatted(1234,false))
+-- print(number.formatted(12345,false))
+-- print(number.formatted(123456,false))
+-- print(number.formatted(1234567,false))
+-- print(number.formatted(12345678,false))
-- print(number.formatted(1234.56,"!","?"))
local p = Cs(
P("-")^0
* (P("0")^1/"")^0
- * (1-P("."))^0
- * (P(".") * P("0")^1 * P(-1)/"" + P(".")^0)
- * P(1-P("0")^1*P(-1))^0
+ * (1-period)^0
+ * (period * P("0")^1 * endofstring/"" + period^0)
+ * P(1-P("0")^1*endofstring)^0
)
function number.compactfloat(n,fmt)
@@ -469,12 +531,11 @@ end
local zero = P("0")^1 / ""
local plus = P("+") / ""
local minus = P("-")
-local separator = S(".")
-local digit = R("09")
+local separator = period
local trailing = zero^1 * #S("eE")
-local exponent = (S("eE") * (plus + Cs((minus * zero^0 * P(-1))/"") + minus) * zero^0 * (P(-1) * Cc("0") + P(1)^1))
+local exponent = (S("eE") * (plus + Cs((minus * zero^0 * endofstring)/"") + minus) * zero^0 * (endofstring * Cc("0") + anything^1))
local pattern_a = Cs(minus^0 * digit^1 * (separator/"" * trailing + separator * (trailing + digit)^0) * exponent)
-local pattern_b = Cs((exponent + P(1))^0)
+local pattern_b = Cs((exponent + anything)^0)
function number.sparseexponent(f,n)
if not n then
@@ -524,62 +585,36 @@ local template = [[
return function(%s) return %s end
]]
-local preamble, environment = "", { }
-
-if oldfashioned then
-
- preamble = [[
-local lpeg=lpeg
-local type=type
-local tostring=tostring
-local tonumber=tonumber
-local format=string.format
-local concat=table.concat
-local signed=number.signed
-local points=number.points
-local basepoints= number.basepoints
-local utfchar=utf.char
-local utfbyte=utf.byte
-local lpegmatch=lpeg.match
-local nspaces=string.nspaces
-local utfpadding=string.utfpadding
-local tracedchar=string.tracedchar
-local autosingle=string.autosingle
-local autodouble=string.autodouble
-local sequenced=table.sequenced
-local formattednumber=number.formatted
-local sparseexponent=number.sparseexponent
-local formattedfloat=number.formattedfloat
- ]]
-
-else
-
- environment = {
- global = global or _G,
- lpeg = lpeg,
- type = type,
- tostring = tostring,
- tonumber = tonumber,
- format = string.format,
- concat = table.concat,
- signed = number.signed,
- points = number.points,
- basepoints = number.basepoints,
- utfchar = utf.char,
- utfbyte = utf.byte,
- lpegmatch = lpeg.match,
- nspaces = string.nspaces,
- utfpadding = string.utfpadding,
- tracedchar = string.tracedchar,
- autosingle = string.autosingle,
- autodouble = string.autodouble,
- sequenced = table.sequenced,
- formattednumber = number.formatted,
- sparseexponent = number.sparseexponent,
- formattedfloat = number.formattedfloat,
- }
-
-end
+local preamble = ""
+
+local environment = {
+ global = global or _G,
+ lpeg = lpeg,
+ type = type,
+ tostring = tostring,
+ tonumber = tonumber,
+ format = string.format,
+ concat = table.concat,
+ signed = number.signed,
+ points = number.points,
+ basepoints = number.basepoints,
+ utfchar = utf.char,
+ utfbyte = utf.byte,
+ lpegmatch = lpeg.match,
+ nspaces = string.nspaces,
+ utfpadding = string.utfpadding,
+ tracedchar = string.tracedchar,
+ autosingle = string.autosingle,
+ autodouble = string.autodouble,
+ sequenced = table.sequenced,
+ formattednumber = number.formatted,
+ sparseexponent = number.sparseexponent,
+ formattedfloat = number.formattedfloat,
+ stripzero = lpeg.patterns.stripzero,
+ stripzeros = lpeg.patterns.stripzeros,
+
+ FORMAT = string.f9,
+}
-- -- --
@@ -593,10 +628,10 @@ setmetatable(arguments, { __index =
end
})
-local prefix_any = C((S("+- .") + R("09"))^0)
-local prefix_sub = (C((S("+-") + R("09"))^0) + Cc(0))
- * P(".")
- * (C((S("+-") + R("09"))^0) + Cc(0))
+local prefix_any = C((sign + space + period + digit)^0)
+local prefix_sub = (C((sign + digit)^0) + Cc(0))
+ * period
+ * (C((sign + digit)^0) + Cc(0))
local prefix_tab = P("{") * C((1-P("}"))^0) * P("}") + C((1-R("az","AZ","09","%%"))^0)
-- we've split all cases as then we can optimize them (let's omit the fuzzy u)
@@ -697,6 +732,17 @@ local format_F = function(f) -- beware, no cast to number
end
end
+-- if string.f9 then
+-- format_F = function(f) -- beware, no cast to number
+-- n = n + 1
+-- if not f or f == "" then
+-- return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or FORMAT(a%s))",n,n,n,n,n)
+-- else
+-- return format("((a%s %% 1 == 0) and format('%%i',a%s) or FORMAT(a%s,'%%%sf'))",n,n,n,f)
+-- end
+-- end
+-- end
+
local format_k = function(b,a) -- slow
n = n + 1
return format("formattedfloat(a%s,%i,%i)",n,b or 0, a or 0)
@@ -840,9 +886,43 @@ local format_L = function()
return format("(a%s and 'TRUE' or 'FALSE')",n)
end
-local format_N = function() -- strips leading zeros
+local format_n = function() -- strips leading and trailing zeros and removes .0
+ n = n + 1
+ return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n)
+end
+
+-- local format_N = function() -- strips leading and trailing zeros (also accepts string)
+-- n = n + 1
+-- return format("tostring(tonumber(a%s) or a%s)",n,n)
+-- end
+
+-- local format_N = function(f) -- strips leading and trailing zeros
+-- n = n + 1
+-- -- stripzero (singular) as we only have a number
+-- if not f or f == "" then
+-- return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or ((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%.9f',a%s)))",n,n,n,n,n)
+-- else
+-- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+-- end
+-- end
+
+-- local format_N = function(f) -- strips leading and trailing zeros
+-- n = n + 1
+-- -- stripzero (singular) as we only have a number
+-- if not f or f == "" then
+-- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or ((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or lpegmatch(stripzero,format('%%.9f',a%s)))",n,n,n,n,n)
+-- else
+-- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+-- end
+-- end
+
+local format_N = function(f) -- strips leading and trailing zeros
n = n + 1
- return format("tostring(tonumber(a%s) or a%s)",n,n)
+ -- stripzero (singular) as we only have a number
+ if not f or f == "" then
+ f = ".9"
+ end -- always a leading number !
+ return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
end
local format_a = function(f)
@@ -882,7 +962,11 @@ local format_m = function(f)
if not f or f == "" then
f = ","
end
- return format([[formattednumber(a%s,%q,".")]],n,f)
+ if f == "0" then
+ return format([[formattednumber(a%s,false)]],n)
+ else
+ return format([[formattednumber(a%s,%q,".")]],n,f)
+ end
end
local format_M = function(f)
@@ -890,7 +974,11 @@ local format_M = function(f)
if not f or f == "" then
f = "."
end
- return format([[formattednumber(a%s,%q,",")]],n,f)
+ if f == "0" then
+ return format([[formattednumber(a%s,false)]],n)
+ else
+ return format([[formattednumber(a%s,%q,",")]],n,f)
+ end
end
--
@@ -902,42 +990,100 @@ end
--
+-- local strip
+--
+-- local format_Z = function(f)
+-- n = n + 1
+-- if not f or f == "" then
+-- f = ".9"
+-- end
+-- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or (strip and lpegmatch(stripzero,format('%%%sf',a%s))) or format('%%%sf',a%s))",n,n,f,n,f,n)
+-- end
+--
+-- function strings.stripformatterzeros()
+-- strip = true
+-- end
+
+-- add(formatters,"texexp", [[texexp(...)]], "local texexp = metapost.texexp")
+--
+-- add(formatters,"foo:bar",[[foo(...)]], { foo = function(...) print(...) return "!" end })
+-- print(string.formatters["foo %3!foo:bar! bar"](1,2,3))
+
+
local format_rest = function(s)
return format("%q",s) -- catches " and \n and such
end
+-- local format_extension = function(extensions,f,name)
+-- local extension = extensions[name] or "tostring(%s)"
+-- local f = tonumber(f) or 1
+-- local w = find(extension,"%.%.%.")
+-- if f == 0 then
+-- if w then
+-- extension = gsub(extension,"%.%.%.","")
+-- end
+-- return extension
+-- elseif f == 1 then
+-- if w then
+-- extension = gsub(extension,"%.%.%.","%%s")
+-- end
+-- n = n + 1
+-- local a = "a" .. n
+-- return format(extension,a,a) -- maybe more times?
+-- elseif f < 0 then
+-- local a = "a" .. (n + f + 1)
+-- return format(extension,a,a)
+-- else
+-- if w then
+-- extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+-- end
+-- -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we
+-- -- cache we don't save much and there are hardly any extensions anyway
+-- local t = { }
+-- for i=1,f do
+-- n = n + 1
+-- -- t[#t+1] = "a" .. n
+-- t[i] = "a" .. n
+-- end
+-- return format(extension,unpack(t))
+-- end
+-- end
+
local format_extension = function(extensions,f,name)
local extension = extensions[name] or "tostring(%s)"
local f = tonumber(f) or 1
local w = find(extension,"%.%.%.")
- if f == 0 then
- if w then
+ if w then
+ -- we have a wildcard
+ if f == 0 then
extension = gsub(extension,"%.%.%.","")
- end
- return extension
- elseif f == 1 then
- if w then
+ return extension
+ elseif f == 1 then
extension = gsub(extension,"%.%.%.","%%s")
- end
- n = n + 1
- local a = "a" .. n
- return format(extension,a,a) -- maybe more times?
- elseif f < 0 then
- local a = "a" .. (n + f + 1)
- return format(extension,a,a)
- else
- if w then
+ n = n + 1
+ local a = "a" .. n
+ return format(extension,a,a) -- maybe more times?
+ elseif f < 0 then
+ local a = "a" .. (n + f + 1)
+ return format(extension,a,a)
+ else
extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+ -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we
+ -- cache we don't save much and there are hardly any extensions anyway
+ local t = { }
+ for i=1,f do
+ n = n + 1
+ -- t[#t+1] = "a" .. n
+ t[i] = "a" .. n
+ end
+ return format(extension,unpack(t))
end
- -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we
- -- cache we don't save much and there are hardly any extensions anyway
- local t = { }
- for i=1,f do
+ else
+ extension = gsub(extension,"%%s",function()
n = n + 1
- -- t[#t+1] = "a" .. n
- t[i] = "a" .. n
- end
- return format(extension,unpack(t))
+ return "a" .. n
+ end)
+ return extension
end
end
@@ -962,6 +1108,7 @@ local builder = Cs { "start",
+ V("C")
+ V("S") -- new
+ V("Q") -- new
+ + V("n") -- new
+ V("N") -- new
+ V("k") -- new
--
@@ -986,7 +1133,7 @@ local builder = Cs { "start",
)
+ V("*")
)
- * (P(-1) + Carg(1))
+ * (endofstring + Carg(1))
)^0,
--
["s"] = (prefix_any * P("s")) / format_s, -- %s => regular %s (string)
@@ -1005,7 +1152,8 @@ local builder = Cs { "start",
--
["S"] = (prefix_any * P("S")) / format_S, -- %S => %s (tostring)
["Q"] = (prefix_any * P("Q")) / format_Q, -- %Q => %q (tostring)
- ["N"] = (prefix_any * P("N")) / format_N, -- %N => tonumber (strips leading zeros)
+ ["n"] = (prefix_any * P("n")) / format_n, -- %n => tonumber (strips leading and trailing zeros, as well as .0, expects number)
+ ["N"] = (prefix_any * P("N")) / format_N, -- %N => tonumber (strips leading and trailing zeros, also takes string)
["k"] = (prefix_sub * P("k")) / format_k, -- %k => like f but with n.m
["c"] = (prefix_any * P("c")) / format_c, -- %c => utf character (extension to regular)
["C"] = (prefix_any * P("C")) / format_C, -- %c => U+.... utf character
@@ -1029,10 +1177,11 @@ local builder = Cs { "start",
["j"] = (prefix_any * P("j")) / format_j, -- %j => %e (float) stripped exponent (irrational)
["J"] = (prefix_any * P("J")) / format_J, -- %J => %E (float) stripped exponent (irrational)
--
- ["m"] = (prefix_tab * P("m")) / format_m, -- %m => xxx.xxx.xxx,xx (optional prefix instead of .)
- ["M"] = (prefix_tab * P("M")) / format_M, -- %M => xxx,xxx,xxx.xx (optional prefix instead of ,)
+ ["m"] = (prefix_any * P("m")) / format_m, -- %m => xxx.xxx.xxx,xx (optional prefix instead of .)
+ ["M"] = (prefix_any * P("M")) / format_M, -- %M => xxx,xxx,xxx.xx (optional prefix instead of ,)
--
["z"] = (prefix_any * P("z")) / format_z, -- %z => skip n arguments
+ -- ["Z"] = (prefix_any * P("Z")) / format_Z, -- %Z => optionally strip zeros
--
["a"] = (prefix_any * P("a")) / format_a, -- %a => '...' (forces tostring)
["A"] = (prefix_any * P("A")) / format_A, -- %A => "..." (forces tostring)
@@ -1057,7 +1206,7 @@ local preset = {
}
local direct =
- P("%") * (S("+- .") + R("09"))^0 * S("sqidfgGeExXo") * P(-1)
+ P("%") * (sign + space + period + digit)^0 * S("sqidfgGeExXo") * endofstring
/ [[local format = string.format return function(str) return format("%0",str) end]]
local function make(t,str)
@@ -1134,36 +1283,22 @@ strings.formatters = { }
-- _connector_ is an experiment
-if oldfashioned then
-
- function strings.formatters.new(noconcat)
- local t = { _type_ = "formatter", _connector_ = noconcat and "," or "..", _extensions_ = { }, _preamble_ = preamble, _environment_ = { } }
- setmetatable(t, { __index = make, __call = use })
- return t
+function strings.formatters.new(noconcat)
+ local e = { } -- better make a copy as we can overload
+ for k, v in next, environment do
+ e[k] = v
end
-
-else
-
- function strings.formatters.new(noconcat)
- local e = { } -- better make a copy as we can overload
- for k, v in next, environment do
- e[k] = v
- end
- local t = { _type_ = "formatter", _connector_ = noconcat and "," or "..", _extensions_ = { }, _preamble_ = "", _environment_ = e }
- setmetatable(t, { __index = make, __call = use })
- return t
- end
-
+ local t = {
+ _type_ = "formatter",
+ _connector_ = noconcat and "," or "..",
+ _extensions_ = { },
+ _preamble_ = "",
+ _environment_ = e,
+ }
+ setmetatable(t, { __index = make, __call = use })
+ return t
end
--- function strings.formatters.new()
--- local t = { _extensions_ = { }, _preamble_ = "", _type_ = "formatter", _n_ = 0 }
--- local m = { _t_ = t }
--- setmetatable(t, { __index = m, __call = use })
--- setmetatable(m, { __index = make })
--- return t
--- end
-
local formatters = strings.formatters.new() -- the default instance
string.formatters = formatters -- in the main string namespace
@@ -1186,27 +1321,17 @@ strings.formatters.add = add
-- registered in the default instance (should we fall back on this one?)
-patterns.xmlescape = Cs((P("<")/"&lt;" + P(">")/"&gt;" + P("&")/"&amp;" + P('"')/"&quot;" + P(1))^0)
-patterns.texescape = Cs((C(S("#$%\\{}"))/"\\%1" + P(1))^0)
+patterns.xmlescape = Cs((P("<")/"&lt;" + P(">")/"&gt;" + P("&")/"&amp;" + P('"')/"&quot;" + anything)^0)
+patterns.texescape = Cs((C(S("#$%\\{}"))/"\\%1" + anything)^0)
patterns.luaescape = Cs(((1-S('"\n'))^1 + P('"')/'\\"' + P('\n')/'\\n"')^0) -- maybe also \0
patterns.luaquoted = Cs(Cc('"') * ((1-S('"\n'))^1 + P('"')/'\\"' + P('\n')/'\\n"')^0 * Cc('"'))
-- escaping by lpeg is faster for strings without quotes, slower on a string with quotes, but
-- faster again when other q-escapables are found (the ones we don't need to escape)
-if oldfashioned then
-
- add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape")
- add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape")
- add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape")
-
-else
-
- add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape = lpeg.patterns.xmlescape })
- add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape = lpeg.patterns.texescape })
- add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape = lpeg.patterns.luaescape })
-
-end
+add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape = lpeg.patterns.xmlescape })
+add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape = lpeg.patterns.texescape })
+add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape = lpeg.patterns.luaescape })
-- -- yes or no:
--
@@ -1243,7 +1368,6 @@ end
local dquote = patterns.dquote -- P('"')
local equote = patterns.escaped + dquote / '\\"' + 1
-local space = patterns.space
local cquote = Cc('"')
local pattern =
@@ -1277,3 +1401,11 @@ function strings.newcollector()
end
end
end
+
+--
+
+local f_16_16 = formatters["%0.5N"]
+
+function number.to16dot16(n)
+ return f_16_16(n/65536.0)
+end
diff --git a/tex/context/base/mkiv/util-tab.lua b/tex/context/base/mkiv/util-tab.lua
index 1b069e2ae..b51c6589a 100644
--- a/tex/context/base/mkiv/util-tab.lua
+++ b/tex/context/base/mkiv/util-tab.lua
@@ -22,7 +22,8 @@ local utftoeight = utf.toeight
local splitter = lpeg.tsplitat(".")
function utilities.tables.definetable(target,nofirst,nolast) -- defines undefined tables
- local composed, t = nil, { }
+ local composed = nil
+ local t = { }
local snippets = lpegmatch(splitter,target)
for i=1,#snippets - (nolast and 1 or 0) do
local name = snippets[i]
@@ -819,3 +820,54 @@ if setinspector then
end
end)
end
+
+-- ordered hashes (for now here but in the table namespace):
+
+-- local t = table.orderedhash()
+--
+-- t["1"] = { "a", "b" }
+-- t["2"] = { }
+-- t["2a"] = { "a", "c", "d" }
+--
+-- for k, v in table.ordered(t) do
+-- ...
+-- end
+
+local mt = {
+ __newindex = function(t,k,v)
+ local n = t.last + 1
+ t.last = n
+ t.list[n] = k
+ t.hash[k] = v
+ end,
+ __index = function(t,k)
+ return t.hash[k]
+ end,
+ __len = function(t)
+ return t.last
+ end,
+}
+
+function table.orderedhash()
+ return setmetatable({ list = { }, hash = { }, last = 0 }, mt)
+end
+
+function table.ordered(t)
+ local n = t.last
+ if n > 0 then
+ local l = t.list
+ local i = 1
+ local h = t.hash
+ local f = function()
+ if i <= n then
+ local k = i
+ local v = h[l[k]]
+ i = i + 1
+ return k, v
+ end
+ end
+ return f, 1, h[l[1]]
+ else
+ return function() end
+ end
+end
diff --git a/tex/context/base/mkiv/util-you.lua b/tex/context/base/mkiv/util-you.lua
index 32a7e07d4..5802e7d7a 100644
--- a/tex/context/base/mkiv/util-you.lua
+++ b/tex/context/base/mkiv/util-you.lua
@@ -30,7 +30,6 @@ utilities.youless = youless
local lpegmatch = lpeg.match
local formatters = string.formatters
-local sortedhash = table.sortedhash
local tonumber, type, next = tonumber, type, next